今天介绍一下哈弗曼编码与解码。
什么是哈夫曼编码?怎么进行哈弗曼编码?以及进行哈夫曼编码之后怎么进行解码工作呢?表急,接下来我会简单介绍一下。
===========================================以下来自我老师的PPT课件====================================================
哈夫曼编码能够使通常的数据传输数量减少到最小。这个编码的发明和这个算法一样十分引人入胜。他的算法也广泛应用于传真机,图象压缩和计算机安全领域。
哈夫曼树:带权路径长度最小的二叉树,亦称最优二叉树。
哈夫曼树的特点:
1、权值越大的叶子结点越靠近根结点,而权值越小的叶子结点越远离根结点。(构造哈夫曼树的核心思想)
2、只有度为0(叶子结点)和度为2(分支结点)的结点,不存在度为1的结点。
3、n个叶结点的哈夫曼树的结点总数为2n-1个。
4、哈夫曼树不唯一,但WPL唯一。
===============================让yogurt偷个懒,嘿嘿嘿========================================
至于哈夫曼树的构造方法:就是把结点的权值按照从小往大依次向上进行合并,如图:(yogurt的字有点丑~~~~(>_<)~~~~大家将就看看就好哈)
编码方法:就是从根结点开始,根结点的左孩子编码为0,右孩子编码为1,再把左孩子结点当做根结点(右孩子结点也当做根结点),继续编码,直到编码到叶子结点为止。
从根节点直到目标结点,一路上经过的编码就是最终的编码啦!
大家可以直接在代码中看到方法的体现,接下来,上代码:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 typedef char** HC;
5
6 typedef struct Node
7 {
8 int weight;
9 char character;
10 struct Node* parent,* lchild,* rchild;
11 }node,*huffmantree;
12
13 huffmantree CreateHuffmantree(node * H, int n);
14 HC code(huffmantree HT, int n);
15 char decode(huffmantree HT, char * c);
16
17 void main()
18 {
19 int w[7] = { 3,4,1,4,2,6,8 };
20 char v[7] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
21 int n = 7,i,j;
22 node H[13];//保存每一个结点,前7位是叶节点(即规定权值),后6位是分支结点
23 for (i = 0, j = 0; i < 13; i++, j++)
24 {
25 if (i < 7)
26 {
27 H[i].weight = w[j];
28 H[i].character = v[j];
29 }
30 else
31 {
32 H[i].weight = 0;
33 H[i].character = ' ';
34 }
35 H[i].parent = 0;
36 H[i].lchild = 0;
37 H[i].rchild = 0;
38 }//哈弗曼树初始化
39
40 huffmantree HT = (huffmantree)malloc(13 * sizeof(node));//分配空间
41 HT = CreateHuffmantree(H, 13);//创建哈夫曼树
42 HC hc = (HC)malloc(7 * sizeof(char*));
43 hc = code(HT,7);//编码
44
45 //验证
46 printf("哈夫曼编码已完成。\n请输入验证字符:");
47 char ch = getchar();
48 for (i = 0; i < 7;i++) //遍历到输入字符的编码指针处
49 {
50 if (HT[i].character == ch)
51 break;
52 } //求第i个字符的编码,在hc[i]处
53 printf("%c的哈夫曼编码为:", ch);
54 puts(hc[i]);
55
56 //解码
57 char m=decode(HT, hc[i]);
58 printf("解码为:");
59 printf("%c", m);
60
61 getchar();
62 return;
63 }
64
65 huffmantree CreateHuffmantree(node * H, int n)
66 {
67 int i = 7, j;
68 while (i < n) //完善H的分支结点,从H[7]-H[n-1]
69 {
70 int min1 = 100, min2 = 100, x = 0, y = 0; //x、y分别记录第二小和最小的元素位置
71 for (j = 0; j <n; j++)
72 {
73 if(H[j].weight>0&&H[j].parent==0) //从已经有值且没有parent指针的结点中找
74 {
75 if (H[j].weight <min2)
76 {
77 if (H[j].weight < min1)
78 {
79 min2 = min1;
80 min1 =H[j].weight;
81 x =y;
82 y = j;
83 }
84 else
85 {
86 min2 = H[j].weight;
87 x = j;
88 }
89 }
90 }
91 } //找到最小的两个元素的位置
92 H[i].weight =H[x].weight + H[y].weight;
93 H[i].lchild = &H[x];
94 H[i].rchild = &H[y];
95 H[x].parent = &H[i];
96 H[y].parent = &H[i];
97
98 i++;
99 }
100 return H;
101 }
102
103 HC code(huffmantree HT, int n)
104 {
105 int i,j;
106 node * c,* f;
107 HC hc = (HC)malloc(7 * sizeof(char*));
108 for (i = 0; i < n; i++) //为n个字符编码,目前为第i个字符编码,存放在哈弗曼树的第i个结点上
109 {
110 j = 6; //每次进来j都要重新变成一次6
111 hc[i] = (char*)malloc(7 * sizeof(char));
112 char a[7]; //编码的临时存放地
113 a[6] = '\0';
114 for (c = &HT[i], f = c->parent; f != 0; c = f, f = f->parent)
115 {
116 if ((f->lchild) == c)
117 a[--j] = '0';
118 else
119 a[--j] = '1';
120 }
121 strcpy(hc[i], &a[j]);
122 }
123 return hc;
124 }
125
126 char decode(huffmantree HT, char * c) //c是哈夫曼编码,末尾是'\0'
127 {
128 //找到哈弗曼树的根结点
129 int i;
130 for (i = 0; HT[i].parent != 0; i++);
131
132 //从根结点开始往下走
133 node *n = &HT[i];
134 while (*c != '\0')
135 {
136 if (*c == '0')
137 n = n->lchild;
138 else
139 n = n->rchild;
140 c++;
141 }
142 return n->character;
143 }
见证奇迹的时刻到啦!
如此,便实现了哈夫曼编码与解码啦~~