堆应用---构造Huffman树(C++实现)
堆:
堆是STL中priority_queue的最高效的实现方式(关于priority_queue的用法:http://www.cnblogs.com/flyoung2008/articles/2136485.html)。
主要分为大根堆和小根堆。
是一棵完全二叉树。
堆的一次插入删除调整的时间复杂度都是logn。
Huffman树:
又称最优二叉树(带权路径中),带权路径长度最小的二叉树应是权值大的外节点离根结点最近的扩充二叉树(权值都在叶节点的二叉树)就是Huffman树。
算法:
将权值对应的节点全部放入一个小根堆中。
每次取出堆顶的两个节点,构造成一个新的节点,循环n-1次(n为节点数量)。
代码如下:
#include<iostream>
using namespace std;
template<class T>
struct TreeNode{
T data;//节点值
TreeNode<T> *left,*right,*parent;//左右孩子
TreeNode(){
left=NULL;
right=NULL;
parent=NULL;
}
TreeNode(T x,TreeNode<T> *l=NULL,TreeNode<T> *r=NULL,TreeNode<T> *p=NULL){
data=x;
left=l;
right=r;
parent=p;
}
bool operator <=(TreeNode<T> &r){
return data<=r.data;
}
bool operator <(TreeNode<T> &r){
return data<r.data;
}
bool operator >=(TreeNode<T> &r){
return data>=r.data;
}
bool operator >(TreeNode<T> &r){
return data>r.data;
}
}; template<class T>
class MinHeap{//最小堆
private:
T *heap;//堆数组
int maxSize;//堆最大容量
int currentSize;//当前容量
public:
MinHeap(int sz=){
maxSize=sz;
heap=new T[maxSize];
currentSize=;
}
~MinHeap(){
delete []heap;
}
T* getHeap(){
return heap;
}
void siftDown(int start,int m){//向下调整堆数组
int i=start;
int j=*i+;
T temp=heap[i];
while(j<=m){
if(j<m&&*heap[j]>*heap[j+]) j++;
if(*temp<=*heap[j]) break;
heap[i]=heap[j];
i=j;
j=*j+;
}
heap[i]=temp;
}
void siftUp(int start){//向上调整堆数组
int i=start;
int j=(i-)/;
T temp=heap[i];
while(i>){
if(*temp>=*heap[j]) break;
heap[i]=heap[j];
i=j;
j=(i-)/;
}
heap[i]=temp;
}
bool insert(const T& x){//插入元素
if(currentSize==maxSize) return false;
heap[currentSize]=x;
siftUp(currentSize);
currentSize++;
return true;
}
bool remove(T& x){//删除元素
if(!currentSize) return false;
x=heap[];
heap[]=heap[currentSize-];
currentSize--;
siftDown(,currentSize-);
return true;
}
}; template<class T>
class HuffmanTree{
public:
HuffmanTree(T w[],int n){//构造Huffman树
TreeNode<T> *temp,*first,*second,*parent;
MinHeap <TreeNode<T>* >hp;
for(int i=;i<n;i++){
temp=new TreeNode<T>(w[i]);
hp.insert(temp);
}
for(int i=;i<n-;i++){
first=new TreeNode<T>;
second=new TreeNode<T>;
hp.remove(first);
hp.remove(second);
parent=new TreeNode<T>;
merge(first,second,parent);
hp.insert(parent);
}
root=parent;
}
void merge(TreeNode<T> *first,TreeNode<T> *second,TreeNode<T>* parent){//选取两个最小带权节点合并
parent->left=first;
parent->right=second;
parent->data=first->data+second->data;
first->parent=parent;
second->parent=parent;
}
~HuffmanTree(){
destroy(root);
}
void destroy(TreeNode<T> *subTree){//递归删除以subTree为根的所有结点
if(subTree!=NULL){
destroy(subTree->left);
destroy(subTree->right);
delete subTree;
}
}
void preOrder(TreeNode<T> *subTree){//前序遍历
if(subTree!=NULL){
cout<<subTree->data<<" ";
preOrder(subTree->left);
preOrder(subTree->right);
}
}
TreeNode<T> *getRoot(){
return root;
}
private:
TreeNode<T> *root;
}; int main(){
int N,*w;
cout<<"输入元素总数:"<<endl;
cin>>N;
w=new int[N];
cout<<"输入这组整数:"<<endl;
for(int i=;i<N;i++){
cin>>w[i];
}
HuffmanTree<int> *ht=new HuffmanTree<int>(w,N);
TreeNode<int> *root=ht->getRoot();
cout<<"Huffman树前序遍历结果:"<<endl;
ht->preOrder(root);
delete ht,w;
return ;
}
堆应用---构造Huffman树(C++实现)的更多相关文章
- Huffman树的构造及编码与译码的实现
哈夫曼树介绍 哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树.所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数) ...
- 构造数列Huffman树总耗费_蓝桥杯
快排! /** 问题描述 Huffman树在编码中有着广泛的应用.在这里,我们只关心Huffman树的构造过程. 给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的 ...
- 数据结构-二叉树(6)哈夫曼树(Huffman树)/最优二叉树
树的路径长度是从树根到每一个结点的路径长度(经过的边数)之和. n个结点的一般二叉树,为完全二叉树时取最小路径长度PL=0+1+1+2+2+2+2+… 带权路径长度=根结点到任意结点的路径长度*该结点 ...
- HUFFMAN 树
在一般的数据结构的书中,树的那章后面,著者一般都会介绍一下哈夫曼(HUFFMAN) 树和哈夫曼编码.哈夫曼编码是哈夫曼树的一个应用.哈夫曼编码应用广泛,如 JPEG中就应用了哈夫曼编码. 首先介绍什么 ...
- 数据结构与算法(周鹏-未出版)-第六章 树-6.5 Huffman 树
6.5 Huffman 树 Huffman 树又称最优树,可以用来构造最优编码,用于信息传输.数据压缩等方面,是一类有着广泛应用的二叉树. 6.5.1 二叉编码树 在计算机系统中,符号数据在处理之前首 ...
- Huffman树与编码
带权路径最小的二叉树称为最优二叉树或Huffman(哈夫曼树). Huffman树的构造 将节点的权值存入数组中,由数组开始构造Huffman树.初始化指针数组,指针指向含有权值的孤立节点. b = ...
- Huffman树
结点定义: /* * Huffman树结点定义 */ struct Node { ElementType weight; // 结点的权值 struct Node *leftChild; // 结点的 ...
- [ACM] POJ 3253 Fence Repair (Huffman树思想,优先队列)
Fence Repair Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 25274 Accepted: 8131 Des ...
- Java蓝桥杯练习题——Huffman树
Huffman树在编码中有着广泛的应用.在这里,我们只关心Huffman树的构造过程. 给出一列数{pi}={p0, p1, -, pn-1},用这列数构造Huffman树的过程如下: 找到{pi}中 ...
随机推荐
- WSL(Windows Subsystem for Linux)--Pico Process Overview
[转载] Windows Subsystem for Linux -- Pico Process Overview Overview This post discusses pico processe ...
- Git + Docker + Jenkins自动化部署web到Linux(Centos)
1.把代码托管到Github上 2.安装Docker 3.安装Jenkins 4.在项目中编写Dockerfile.publish.sh (1)Dockerfile内容 # 基于dotnet基础环境构 ...
- 基于Linux下catalog方式的 Oracle 备份策略(RMAN)
--********************************** -- 基于Linux下 Oracle 备份策略(RMAN) --******************************* ...
- 类LinkedList
LinkedList特点 java.util.LinkedList 集合数据存储的结构是链表结构.方便元素添加.删除的.LinkedList是List的子类,List中的方法LinkedList都是可 ...
- Neutron vxlan network--L2 Population
L2 Population 是用来提高 VXLAN 网络 Scalability 的. 通常我们说某个系统的 Scalability 好,其意思是: 当系统的规模变大时,仍然能够高效地工作. L2 ...
- nginx简单的命令
nginx -s reload|reopen|stop|quit #重新加载配置|重启|停止|退出 nginx nginx -t #测试配置是否有语法错误 nginx [-?hvVtq] [-s si ...
- [代码]解析nodejs的require,吃豆人的故事
最近在项目中需要对nodejs的require关键字做解析,并且替换require里的路径.一开始我希望nodejs既然作为脚本语言,内核提供一个官方的parser库应该是一个稳定可靠又灵活的渠道,然 ...
- js面向对象学习
纯属笔记,加强记忆,不是教程,欢迎纠错,没有逻辑,不太适合学习使用. -------------- 继承多态等太多概念难以理解,还是从实践中慢慢学吧!争取能大致看懂网上的开源的代码. -------- ...
- dataTable tab栏切换时错位解决办法
做后台管理类网站肯定要写列表,首选dataTable,功能强大 最近在做一个tab栏切换时发现了一个很诡异的事情:表头错位了! 主要时因为当table被隐藏后,table的header宽度会计算错乱, ...
- 【python 字符串】 字符串的相关方法(一)
将字符串首字母变为大写 -> capitalize() 方法 # 将字符串的首字母转换为大写 text = 'alet' ret = text.capitalize() print(ret) ...