哈夫曼编码

来源:互联网 发布:斧子演示 知乎 编辑:程序博客网 时间:2024/06/16 23:14

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

生成哈夫曼树:

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

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

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

代码:

#include<iostream>#include<string>#include<algorithm>#include<cstring>using namespace std;#define mem(x) memset(x,0,sizeof(x))#define MaxN 30//存放剩余没被选出的节点信息struct sum{  double s;  int num;  bool operator < (sum x){    return s<x.s;  }}tree[MaxN+5];//存放之后每个新创建节点的孩子节点和自身编号信息//也是由这个来存放树struct parent{  int num;  int left;  int right;}par[2*MaxN+10];//存放每个字符信息struct data{  char character;  double value;  string code;  //存放每个字符的哈夫曼编码}A[MaxN+5];//遍历树并找到编码void FindCode(int num,string code=""){  if(par[num].left!=0){    FindCode(par[num].left,code+'0');  }  if(par[num].right!=0){    FindCode(par[num].right,code+'1');  }  if((par[num].left+par[num].right)==0){    A[num].code=code;  }}void huffman(int N){  sum temp;  mem(A);mem(par);mem(tree);  for(int i=1;i<=N;i++){    cin>>A[i].character>>A[i].value;    tree[i].num=i;    tree[i].s=A[i].value;    par[i].num=i;  }  //建树  sort(tree+1,tree+N+1);  for(int i=1;i<=N-1;i++){    par[N+i].left=tree[i].num;    par[N+i].right=tree[i+1].num;    tree[i+1].s+=tree[i].s;    tree[i+1].num=N+i;    int j=i+1;    temp=tree[i+1];    //下面是排序 因为数据量小所以选择常量时间低的插入排序    //如果编码数据多可以利用归并排序的原理进行排序优化时间复杂度    //也就是合并后的节点值按顺序放入一个新的队列 这个队则会有序 连续两次选出两个队列对头元素中较小的一个    while(temp.s>tree[j+1].s&&j<N){      tree[j]=tree[j+1];      j++;    }    tree[j]=temp;  }  //下面这个函数用来递归遍历树并记录下正确编码  FindCode(2*N-1);}//测试用的主函数int main(){  int num;  cout<<"how many characters do you want to encoding? please input a number."<<endl;  cin>>num;  cout<<"please input all characters and weight value."<<endl;  huffman(num);  cout<<"ans:"<<endl;  for(int i=1;i<=num;i++){    cout<<A[i].character<<":"<<A[i].code<<endl;  }}


原创粉丝点击