7-14 构造哈夫曼树和哈夫曼编码的算法
2018-03-11 12:51
561 查看
//构造哈夫曼树和哈夫曼编码的算法 #include <stdio.h> #include <string.h> #define N 50 //叶子结点数 #define M 2*N-1 //树中结点总数 typedef struct { char data[5]; //结点值 double weight; //权重 int parent; //双亲结点 int lchild; //左孩子结点 int rchild; //右孩子结点 } HTNode; typedef struct { char cd ; //存放哈夫曼码 int start; } HCode; void CreateHT(HTNode ht[],int n0) //构造哈夫曼树 { int i,k,lnode,rnode; double min1,min2; for (i=0;i<2*n0-1;i++) //所有节点的相关域置初值-1 ht[i].parent=ht[i].lchild=ht[i].rchild=-1; //传进来的ht数组中每个结点只是赋值了data数组,parent\lchild\rchild都没有赋值 //将结点的parent\lchild\rchild初始为-1作为未参与哈夫曼树构造的标志 for (i=n0;i<=2*n0-2;i++) //构造哈夫曼树的n0-1个节点,即生成原先没有的n0-1个父结点 { min1=min2=32767; //这里min1和min2必须赋初值才能进行比较,由于比的是小,为了不影响实际的比较结果, //只能尽可能取大的,为保险故赋值为int类型的最大值 lnode=rnode=-1; //lnode和rnode为最小权重的两个节点位置,2^16-1 for (k=0;k<=i-1;k++) //在ht[0..i-1]中找权值最小的两个节点 if (ht[k].parent==-1) //只在尚未构造二叉树的节点中查找 { if (ht[k].weight<min1) { min2=min1;rnode=lnode; min1=ht[k].weight; lnode=k; } else if (ht[k].weight<min2||ht[k].weight==min1) { min2=ht[k].weight;rnode=k; } } ht[i].weight=ht[lnode].weight+ht[rnode].weight; ht[i].lchild=lnode;ht[i].rchild=rnode; //ht[i]作为双亲节点 ht[lnode].parent=i;ht[rnode].parent=i; } } void CreateHCode(HTNode ht[],HCode hcd[],int n0) //构造哈夫曼树编码 { int i,f,c; HCode hc; for (i=0;i<n0;i++) //根据哈夫曼树求哈夫曼编码 { hc.start=n0;c=i; f=ht[i].parent; while (f!=-1) //循环直到无双亲节点即到达树根节点 { if (ht[f].lchild==c) //当前节点是双亲节点的左孩子 hc.cd[hc.start--]='0'; else //当前节点是双亲节点的右孩子 hc.cd[hc.start--]='1'; c=f;f=ht[f].parent; //再对双亲节点进行同样的操作 } hc.start++; //start指向哈夫曼编码最开始字符 hcd[i]=hc; } } void DispHCode(HTNode ht[],HCode hcd[],int n0) //输出哈夫曼树编码 { int i,k; double sum=0,m=0; int j; printf(" 输出哈夫曼编码:\n"); //输出哈夫曼编码 for (i=0;i<n0;i++) { j=0; printf(" %s:\t",ht[i].data); //printf("%s",hcd[i].cd);验证hcd[i].cd[start~n0]才是一个结点对应的哈夫曼树编码,并非从cd[从0开始] for (k=hcd[i].start;k<=n0;k++) { printf("%c",hcd[i].cd[k]); j++; //一个结点的哈夫曼编码的长度对应其结点边数,故输出一个字符,增加一条边数 } m+=ht[i].weight;//在这个问题上权值之和一定为1,即m为1 sum+=ht[i].weight*j; printf("\n"); } //printf("\n m=%g sum=%g",m,sum); %g格式不输出小数点后无意义的零 printf("\n 平均长度=%g\n",1.0*sum/m); //在这个问题上,1.0*sum/m意义不大 } int main() { int n=8,i; //n表示初始字符串的个数 char *str[]={"a","b","c","d","e","f","g","h"}; double fnum[]={0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.1}; HTNode ht[M]; HCode hcd ; for (i=0;i<n;i++) { strcpy(ht[i].data,str[i]); ht[i].weight=fnum[i]; } printf("\n"); //83行到92行代码的作用是为创建哈夫曼树提供ht[]数组 CreateHT(ht,n); CreateHCode(ht,hcd,n); DispHCode(ht,hcd,n); printf("\n"); for(i=0;i<n;i++) //printf(" %s ",ht[i].data);验证ht[0~n0-1]为叶子结点 return 1; }
相关文章推荐
- 哈夫曼树构造及编码算法应用之26个字母的哈夫曼编码
- GZIP压缩原理分析(14)——第五章 Deflate算法详解(五05) 预备知识(04) 前缀码、原始哈夫曼编码原理以及deflate所用哈夫曼编码的性质
- 构造哈夫曼树 求哈弗曼编码 (贪心算法实现)算法导论p232
- 哈夫曼树构造 哈夫曼编码得到
- GZIP压缩原理分析(29)——第五章 Deflate算法详解(五20) 动态哈夫曼编码分析(09)构建哈夫曼树(01)
- GZIP压缩原理分析(30)——第五章 Deflate算法详解(五21) 动态哈夫曼编码分析(10)构建哈夫曼树(02)
- GZIP压缩原理分析(31)——第五章 Deflate算法详解(五22) 动态哈夫曼编码分析(11)构建哈夫曼树(03)
- 哈夫曼树的构造算法,哈夫曼编码算法
- GZIP压缩原理分析(32)——第五章 Deflate算法详解(五23) 动态哈夫曼编码分析(12)构建哈夫曼树(04)
- 哈夫曼树,及哈夫曼编码的构造
- 数据结构之构造哈夫曼树及哈夫曼编码
- GZIP压缩原理分析(33)——第五章 Deflate算法详解(五24) 动态哈夫曼编码分析(13)构建哈夫曼树(05)
- 哈夫曼树和哈夫曼编码基本概念及构造(上篇)
- 哈夫曼树的建立和哈夫曼编码的构造
- 哈夫曼树的构造与哈夫曼编码
- 数据结构上机【构造哈夫曼树,并输出对应节点的哈夫曼编码】
- GZIP压缩原理分析(23)——第五章 Deflate算法详解(五14) 动态哈夫曼编码分析(03) LZ77过程(02)
- 哈夫曼编码-->输入权重,构造哈夫曼树并输出相应哈夫曼编码(c语言)
- 给定权值 {19,01,23,14,55,20,84,27 },构造相应的哈夫曼树,计算WPL.
- 构建哈夫曼树并打印哈夫曼编码