设为首页 加入收藏

TOP

C语言之霍夫曼编码学习(一)
2015-01-21 11:08:25 来源: 作者: 【 】 浏览:53
Tags:语言 霍夫 编码 学习


?
1,霍夫曼编码描述
哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。 在计算机信息处理中,“哈夫曼编码”是一种一致性编码法(又称“熵编码法”),用于数据的无损耗压缩。这一术语是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。这种方法是由David.A.Huffman发展起来的。 例如,在英文中,e的出现概率很高,而z的出现概率则最低。当利用哈夫曼编码对一篇英文进行压缩时,e极有可能用一个位(bit)来表示,而z则可能花去25个位(不是26)。用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个位。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。若能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。

2,问题描述
霍夫曼编码前首先要统计每个字的字频,即出现次数,例如:

/

?

1、将所有字母出现的次数以从小到大的顺序排序,如上图

2、每个字母都代表一个终端节点(叶节点),比较F.O.R.G.E.T五个字母中每个字母的出现频率,将最小的两个字母频率相加合成一个新的节点。如上图所示,发现F与O的频率最小,故相加2+3=5,将F、O组成一个树,F为左节点,O为右节点,(FO)为根节点,每个节点的取值为其出现频率(FO的出现频率为5)

3、比较5.R.G.E.T,发现R与G的频率最小,故相加4+4=8,将RG组成一个新的节点

4、比较5.8.E.T,发现5与E的频率最小,故相加5+5=10,因此将FO作为左节点,E作为右节点,FOE作为根节点

5、比较8.10.T,发现8与T的频率最小,故相加8+7=15,将RG作为左节点,T作为右节点,RGT作为根节点

6、最后剩10.15,没有可以比较的对象,相加10+15=25,FOE作为左节点,RGT作为右节点

?

根节点不取值,每个左子节点取值0,右子节点取值1,将每个字母从根节点开始遍历,沿途的取值组成编码:

/

?

?

首先选择一个文本,统计每个字符出现的次数,组成以下数组:
typedef struct FrequencyTreeNode {
int freq;
char c;
struct FrequencyTreeNode *left;
struct FrequencyTreeNode *right;
} FrequencyTreeNodeStruct, *pFrequencyTreeNodeStruct;

然后将获得的数组frequencies进行排序,按照freq由小到大的顺序组成一个二叉查找树,FrequencyTreeNodeStruct,从二叉查找树中找到最小的节点,从树中删除,再取最小的节点,两个子节点,组成一个新的树,根节点c为0,freq为两个子节点的和,加入frequencies中,并排序,重复该步骤,一直到frequencies中只有一个节点,则该节点为Huffman coding tree的根节点

?

以short类型按照前述的规则为每个字符编码,尔后将文本翻译为Huffman coding,再通过Huffman coding tree进行解码,验证编码的正确性。


3,代码实现

  1. #include
  2. #define n 5 //叶子数目
  3. #define m (2*n-1) //结点总数
  4. #define maxval 10000.0
  5. #define maxsize 100 //哈夫曼编码的最大位数
  6. ?
  7. ?
  8. //定义结构体
  9. typedef struct FrequencyTreeNode {
  10. int freq;
  11. char c;
  12. struct FrequencyTreeNode *left;
  13. struct FrequencyTreeNode *right;
  14. } FrequencyTreeNodeStruct, *pFrequencyTreeNodeStruct;
  15. ?
  16. ?
  17. FrequencyTreeNodeStruct frequencies[MAXALPABETNUM];
  18. ?
  19. ?
  20. typedef struct
  21. {
  22. char bits[n]; //位串
  23. int start; //编码在位串中的起始位置
  24. char ch; //字符
  25. }codetype;
  26. ?
  27. ?
  28. // 读取文件内容,统计字符以及出现频率
  29. void readTxtStatistics(char* fileName)
  30. {
  31. unsigned int nArray[52] = {0};
  32. unsigned int i, j;
  33. char szBuffer[MAXLINE];
  34. int k=0;
  35. // 读取文件内容
  36. FILE* fp = fopen(fileName, );
  37. if (fp != NULL)
  38. { /*读取文件内容,先统计字母以及出现次数*/
  39. while(fgets(szBuffer, MAXLINE, fp)!=NULL)
  40. {
  41. for(i = 0; i < strlen(szBuffer); i++)
  42. {
  43. if(szBuffer[i] <= 'Z' && szBuffer[i] >= 'A')
  44. {
  45. j = szBuffer[i] - 'A';
  46. }
  47. else if(szBuffer[i] <= 'z' && szBuffer[i] >= 'a')
  48. {
  49. j = szBuffer[i] - 'a' + 26;
  50. }
  51. else
  52. continue;
  53. nArray[j]++;
  54. }
  55. }
  56. ?
  57. ?
  58. // 然后赋值给frequencies数组
  59. for(i = 0, j = 'A'; i < 52; i++, j++)
  60. {
  61. if (nArray[i] >0)
  62. {
  63. /*****/
  64. frequencies[k].c=j;
  65. frequencies[k].freq=nArray[i];
  66. frequencies[k].left=NULL;
  67. frequencies[k].right=NULL;
  68. k++;
  69. printf(%c:%d\n, j, nArray[i]);
  70. }
  71. if(j == 'Z')
  72. j = 'a' - 1;
  73. }
  74. }
  75. }
  76. ?
  77. ?
  78. //建立哈夫曼树
  79. void huffMan(frequencies tree[]){
  80. int i,j,p1,p2;//p1,p2分别记住每次合并时权值最小和次小的两个根结点的下标
  81. float small1,small2,f;
  82. char c;
  83. for(i=0;i
  84. {
  85. tree[i].parent=0;
  86. tree[i].lchild=-1;
  87. tree[i].rchild=-1;
  88. tree[i].weight=0.0;
  89. }
  90. printf(【依次读入前%d个结点的字符及权值(中间用空格隔开)】\n,n);
  91. ?
  92. ?
  93. //读入前n个结点的字符及权值
  94. for(i=0;i
  95. {
  96. printf(输入第%d个字符为和权值,i+1);
  97. scanf(%c %f,&c,&f);
  98. getchar();
  99. tree[i].ch=c;
  100. tree[i].weight=f;
  101. }
  102. //进行n-1次合并,产生n-1个新结点
  103. for(i=n;i
  104. {
  105. p1=0;p2=0;
  106. //maxval是float类型的最大值
  107. small1=maxval;small2=maxval;
  108. //选出两个权值最小的根结点
  109. for(j=0;j
  110. {
  111. if(tree[j].parent==0)
  112. if(tree[j].weight
  113. {
  114. small2
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言实现多态 下一篇OC-探究private修饰的属性能否被..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: