哈夫曼编码

Posted taming

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈夫曼编码相关的知识,希望对你有一定的参考价值。

先生成哈夫曼树,然后遍历树得到编码。

生成哈夫曼树:

每个字符对应一个权重初始化为一个节点,所有节点按照权重排序,然后选出两个权重最小的两个节点和创建一个新的节点,选出的两个节点作为新创建节点的左右孩子节点,新节点的权值为两个孩子节点的和,然后将新节点放入原来的没选取出的节点中重新排序,重复上述步骤,直到只剩下一个节点,也就是这棵哈夫曼树的根节点了。

最后从根节点开始遍历树,统计从根节点到叶节点的路劲对应的编码就能得到最终结果了。

创建新节点放入剩余节点重新排序这一步骤的时候,如果字符量少可以选择常量时间很低的插入排序,如果数据量大可以利用归并排序的原理,原始节点排序后入队列A,新创建一个队列B,将新创建的节点入队B,因为后创建的节点的权值一定比先创建的节点的权值更大,所以依次入队的话将队列元素将按从小到大排列,之后每次找最小值就只需要较队头元素然后选中较小的一个出队。

代码:

 

[cpp] view plain copy
 
  1. #include<iostream>  
  2. #include<string>  
  3. #include<algorithm>  
  4. #include<cstring>  
  5. using namespace std;  
  6.   
  7. #define mem(x) memset(x,0,sizeof(x))  
  8. #define MaxN 30  
  9. //存放剩余没被选出的节点信息  
  10. struct sum{  
  11.   double s;  
  12.   int num;  
  13.   bool operator < (sum x){  
  14.     return s<x.s;  
  15.   }  
  16. }tree[MaxN+5];  
  17. //存放之后每个新创建节点的孩子节点和自身编号信息  
  18. //也是由这个来存放树  
  19. struct parent{  
  20.   int num;  
  21.   int left;  
  22.   int right;  
  23. }par[2*MaxN+10];  
  24. //存放每个字符信息  
  25. struct data{  
  26.   char character;  
  27.   double value;  
  28.   string code;  //存放每个字符的哈夫曼编码  
  29. }A[MaxN+5];  
  30. //遍历树并找到编码  
  31. void FindCode(int num,string code=""){  
  32.   if(par[num].left!=0){  
  33.     FindCode(par[num].left,code+‘0‘);  
  34.   }  
  35.   if(par[num].right!=0){  
  36.     FindCode(par[num].right,code+‘1‘);  
  37.   }  
  38.   if((par[num].left+par[num].right)==0){  
  39.     A[num].code=code;  
  40.   }  
  41. }  
  42.   
  43. void huffman(int N){  
  44.   sum temp;  
  45.   mem(A);mem(par);mem(tree);  
  46.   for(int i=1;i<=N;i++){  
  47.     cin>>A[i].character>>A[i].value;  
  48.     tree[i].num=i;  
  49.     tree[i].s=A[i].value;  
  50.     par[i].num=i;  
  51.   }  
  52.   //建树  
  53.   sort(tree+1,tree+N+1);  
  54.   for(int i=1;i<=N-1;i++){  
  55.     par[N+i].left=tree[i].num;  
  56.     par[N+i].right=tree[i+1].num;  
  57.     tree[i+1].s+=tree[i].s;  
  58.     tree[i+1].num=N+i;  
  59.     int j=i+1;  
  60.     temp=tree[i+1];  
  61.     //下面是排序 因为数据量小所以选择常量时间低的插入排序  
  62.     //如果编码数据多可以利用归并排序的原理进行排序优化时间复杂度  
  63.     //也就是合并后的节点值按顺序放入一个新的队列 这个队则会有序 连续两次选出两个队列对头元素中较小的一个  
  64.     while(temp.s>tree[j+1].s&&j<N){  
  65.       tree[j]=tree[j+1];  
  66.       j++;  
  67.     }  
  68.     tree[j]=temp;  
  69.   }  
  70.   //下面这个函数用来递归遍历树并记录下正确编码  
  71.   FindCode(2*N-1);  
  72. }  
  73.   
  74. //测试用的主函数  
  75. int main(){  
  76.   int num;  
  77.   cout<<"how many characters do you want to encoding? please input a number."<<endl;  
  78.   cin>>num;  
  79.   cout<<"please input all characters and weight value."<<endl;  
  80.   huffman(num);  
  81.   cout<<"ans:"<<endl;  
  82.   for(int i=1;i<=num;i++){  
  83.     cout<<A[i].character<<":"<<A[i].code<<endl;  
  84.   }  
  85. }  

以上是关于哈夫曼编码的主要内容,如果未能解决你的问题,请参考以下文章

哈夫曼编码C语言实现

霍夫曼编码

哈夫曼编码怎么求

我们有个数据结构的哈夫曼编码解码的课程设计,你能帮帮我吗

哈夫曼编码

哈夫曼编码记录