您的位置:首页 > 其它

任意ASCII码格式信息的huffman tree压缩(编码)和解压(译码)

2013-06-28 10:29 309 查看
任意ASCII码格式信息的huffman tree压缩(编码)和解压(译码)
作者:牛老师,华清远见嵌入式学院讲师。

计算机实践中发现,大多数信息的表达都存在着一定的冗余度,有效的降低这种冗余度可以使我们用更小的空间存储更大的数据量,同时在有限的通信带宽的情况下,可以传输更多的信息,等等……。那用什么办法可以降低这种冗余度,这里我们学习其中的一种huffman treee压缩(编码)和解压(译码)方法。

huffman tree的压缩和解压的过程如下:

1、描述

对于任意的ASCII格式的信息aba$a@ba*a$a,先统计它们的出现频率a6,b2,$2,*1,@1,然后分别用不等长的01串来编码它们,如a1,b00,$011,*0100,@0101,最后用01串替换原来的信息,得到100101110101001010010111,并按二进制位组合,这样就可以得到压缩后的文件。

相对应,解压时必须知道编码a1,b00,$011,*0100,@0101,然后根据100101110101001010010111一步步解压得到aba$a@ba*a$a原始信息。

2、分析

为了解压成功,首先必须保证任何已经编码的单个字符不能是其他字符编码的前缀,也就是说用1编码a以后,其他字符编码不能以1开头。为了实现压缩的最小,同时要保证出现频率最高的字符编码最短,频率最低的编码最长。

3、方法

通过描述和分析,我们明白这种方法是可以实现压缩文件的,用什么办法可以实现这种方法呢?使用最优二叉树也就是huffman tree可以实现上面的方法,步骤如下:

1) 将a6,b2,$2,*1,@1按照频率值从小到大有序入队,出队两个元素,分别以它们为左右子树,建立二叉树,并将它们出现次数之和作为根节点,把根节点有序入队。

@1 *1 $2 b2 a6
2 $2 b2 a6

/ \

@1 *1
2) 然后重复1步骤直到队中只剩下一个节点,该节点就是所求huffman tree的根节点,最后按照左0,右1进行编码a1,b00,$011,*0100,@0101。

b2 4 a6

/ \

2 $2

/ \

@1 *1
6 a6

/ \

b2 4

/ \

2 $2

/ \

@1 *1
12

0/ 1\

6 a6

0/ 1\ 1

b2 4

00 0/ 1\

2 $2

0/ 1\ 011

*1 @1

0100 0101
4、步骤

第一步:统计aba$a@ba*a$a字符出现的频率,a6,b2,$2,*1,@1。

第二步:去除重复的字符ab$@*。

第三步:创建huffman tree,对ab$@*进行编码a1,b00,$011,*0100,@0101。

第四步:aba$a@ba*a$a根据编码a1,b00,$011,*0100,@0101压缩为10010111010

1001010010111。

第五步:100101110101001010010111根据huffman tree解压为aba$a@ba*a$a。

5、实现

treehuffman.c

1. #include <stdio.h>

2. #include <stdlib.h>

3. #include <string.h>

4. #include "treehuffman.h"

5. #include "../queue/queuelink.h"

6.

7. treehuffman *treecreate(char *s)

8. {

9. int w[256] = {};

10. int i;

11. char c[256] = {}, *pc = c;

12. queuelink *q = queuecreate();

13. queuedata temp;

14.

15. // 第一步

16. while(*s != '\0')

17. {

18. w[(int)*s++]++;

19. }

20.

21. // 第二步

22. for(i=0; i<256; i++)

23. {

24. if(w[i] != 0)

25. {

26. *pc++ = i;

27. }

28. }

29.

30. // 第三步

31. pc = c;

32. while(*pc != '\0')

33. {

34. temp = (treehuffman *)malloc(sizeof(treehuffman));

35.

36. temp->c = *pc;

37. temp->w = w[(int)*pc++];

38. temp->code[0] = '\0';

39. temp->lchild = temp->rchild = NULL;

40.

41. queueenterorder(q, temp);

42. }

43.

44. while(q->front->next != q->rear)

45. {

46. temp = (treehuffman *)malloc(sizeof(treehuffman));

47.

48. temp->code[0] = '\0';

49. temp->lchild = queuedelete(q);

50. temp->rchild = queuedelete(q);

51. temp->w = temp->lchild->w+temp->rchild->w;

52.

53. queueenterorder(q, temp);

54. }

55.

56. return queuedelete(q);

57. }

58.

59. // 第四步

60. char *treecompress(treehuffman *t, char *s, char *compressed)

61. {

62. queuelink *q = queuecreate();

63. queuedata temp;

64. char *code[256];

65.

66. queueenter(q, t);

67.

68. while(queueempty(q) == 0)

69. {

70. temp = queuedelete(q);

71.

72. if(temp->lchild==NULL && temp->rchild==NULL)

73. {

74. code[(int)temp->c] = temp->code;

75. printf("%c(%d) : %s\n", temp->c, temp->w, temp->code);

76. }

77.

78. if(temp->lchild != NULL)

79. {

80. strcpy(temp->lchild->code, temp->code);

81. strcat(temp->lchild->code, "0");

82. queueenter(q, temp->lchild);

83. }

84.

85. if(temp->rchild != NULL)

86. {

87. strcpy(temp->rchild->code, temp->code);

88. strcat(temp->rchild->code, "1");

89. queueenter(q, temp->rchild);

90. }

91. }

92.

93. while(*s != '\0')

94. {

95. strcat(compressed, code[(int)*s++]);

96. }

97.

98. return compressed;

99. }

100.

101. // 第五步

102. char *treeuncompress(treehuffman *t, char *compressed, char *compress)

103. {

104. char *p = compress;

105. treehuffman *temp = t;

106.

107. while(*compressed != '\0')

108. {

109. if(*compressed++ == '0')

110. {

111. temp = temp->lchild;

112. }

113. else

114. {

115. temp = temp->rchild;

116. }

117.

118. if(temp->lchild==NULL && temp->rchild==NULL)

119. {

120. *compress++ = temp->c;

121. temp = t;

122. }

123. }

124.

125. return p;

126. }

1treehuffman.h

127. #ifndef __TREEHUFFMAN_H__

128. #define __TREEHUFFMAN_H__

129.

130. typedef char treedata;

131.

132. typedef struct tree

133. {

134. treedata c;

135. int w;

136. char code[16];

137. struct tree *lchild, *rchild;

138. }treehuffman;

139.

140. extern treehuffman *treecreate(char *s);

141. extern char *treecompress(treehuffman *t, char *s, char *compressed);

142. extern char *treeuncompress(treehuffman *t, char *compressed, char *compress);

143.

144. #endif

注意:对于a6,b2,$2,*1,@1来说,结果可能有几种,可能是a1,b00,$011,*0100,@0101,也可以是a1,$00,b011,@0100,*0101。这是因为统计的频率中有相等的,所以在有序入队时他们可能是左子树,也可能是右子树,所以出来的结果可能与程序本身的处理有关,不过不影响最终的压缩率。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: