今天介绍一下哈弗曼编码与解码。
什么是哈夫曼编码?怎么进行哈弗曼编码?以及进行哈夫曼编码之后怎么进行解码工作呢?表急,接下来我会简单介绍一下。
===========================================以下来自我老师的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 }
见证奇迹的时刻到啦!
如此,便实现了哈夫曼编码与解码啦~~