哈夫曼树编码并解码(加强版)
本代码流程:
随机输入一段字符串--->根据输入字符串得到每个字符权重(频数)并输出--->得到每个字符对应哈夫曼编码并输出--->输入一段哈夫曼编码--->利用每个字符对应的哈夫曼编码来解码
技术支持:
1.如何得到每个自负权重,上上个博客,网址如下:
https://www.cnblogs.com/2019-12-10-18ykx/p/12898245.html
2.如何判断两字符串是否相等,上个博客,网址如下:
https://www.cnblogs.com/2019-12-10-18ykx/p/12902210.html
这里是代码:
main.cpp
1 #include <iostream> 2 #include "哈夫曼树.h" 3 #include <map> 4 #include <set> 5 #include <string> 6 using namespace std; 7 int main() { 8 HuffmanTree HT; 9 HuffmanCode HC; 10 int *wei, n = 0, i; 11 char *ch; 12 string s; 13 cout << "请输入一段字符串(字符串长度不要超过100):"; 14 cin >> s; 15 map<char, int> m; 16 int j = 1; 17 for (auto & i : s) 18 { 19 m[i]++; 20 } 21 for (auto & i : m) 22 { 23 cout << i.first << ' ' << i.second << endl; 24 n++; 25 } 26 wei = (int *)malloc((n + 1) * sizeof(int)); 27 ch = (char*)malloc((n + 1) * sizeof(char)); 28 for (auto & i : m) 29 { 30 ch[j] = i.first; 31 wei[j] = i.second; 32 j++; 33 } 34 createHuffmanTree(&HT, n, wei, ch); 35 createHuffmanCode(&HT, &HC, n); 36 return 0; 37 }
哈夫曼树.h(其实Decode解码函数可以用void类型的,但是我懒得改了)
1 #include <iostream> 2 using namespace std; 3 typedef struct { 4 int weight; 5 int lchild, rchild, parent; 6 char c; 7 }Node, *HuffmanTree; 8 typedef char *HuffmanCode; 9 void select(HuffmanTree *huffmantree, int n, int *s1, int *s2); 10 void createHuffmanTree(HuffmanTree *huffmantree, int n, int w[], char cha[]); 11 void createHuffmanCode(HuffmanTree *huffmantree, HuffmanCode *huffmancode, int n); 12 string Decode(HuffmanTree *huffmantree, HuffmanCode *huffmancode, int n, string s);
哈夫曼树.cpp
1 #include <iostream> 2 #include "哈夫曼树.h" 3 #include <string> 4 using namespace std; 5 //找权值最小的结点 6 void select(HuffmanTree *huffmantree,int n,int *s1,int *s2) { 7 int i;//作为计数器 8 int min1, min2, m1=0, m2;//权值最小和权值次小,权值最小和次小所在位置 9 min1 = 999; 10 min2 = 999; 11 for (i = 1; i <= n; i++) { 12 if ((*huffmantree)[i].parent == 0) {//保证父节点不为0 13 if (min1 > (*huffmantree)[i].weight) { 14 min2 = min1; 15 m2 = m1; 16 min1 = (*huffmantree)[i].weight; 17 m1 = i; 18 } 19 else if (min2 > (*huffmantree)[i].weight) { 20 min2 = (*huffmantree)[i].weight; 21 m2 = i; 22 } 23 } 24 } 25 *s1 = m1; 26 *s2 = m2; 27 } 28 //初始化节点,构造哈夫曼树 29 void createHuffmanTree(HuffmanTree *huffmantree,int n,int w[],char cha[]) { 30 int i; 31 int m = 2 * n - 1; 32 *huffmantree = (HuffmanTree)malloc((m + 1) * sizeof(Node)); 33 //叶子节点的初始化 34 for (i = 1; i <= n; i++) { 35 (*huffmantree)[i].parent = 0; 36 (*huffmantree)[i].lchild = 0; 37 (*huffmantree)[i].rchild = 0; 38 (*huffmantree)[i].c = cha[i]; 39 (*huffmantree)[i].weight = w[i]; 40 } 41 //非叶子节点的初始化 42 for (i = n + 1; i <= m; i++) { 43 (*huffmantree)[i].parent = 0; 44 (*huffmantree)[i].lchild = 0; 45 (*huffmantree)[i].rchild = 0; 46 (*huffmantree)[i].weight = 0; 47 } 48 //开始构建哈夫曼树 49 cout << "哈夫曼树:" << endl; 50 cout << "父节点权值 (左孩子权值 右孩子权值)" << endl; 51 int s1, s2;//这是两个权值最小的结点所在位置 52 for (i = n + 1; i <= m; i++) { 53 //寻找parent为0,且权值最小的两个结点 54 select(huffmantree, i-1, &s1, &s2); 55 (*huffmantree)[s1].parent = i; 56 (*huffmantree)[s2].parent = i; 57 (*huffmantree)[i].lchild = s1; 58 (*huffmantree)[i].rchild = s2; 59 (*huffmantree)[i].weight = (*huffmantree)[s1].weight + (*huffmantree)[s2].weight; 60 cout << " " << (*huffmantree)[i].weight << " " << (*huffmantree)[s1].weight << " " << (*huffmantree)[s2].weight << endl; 61 } 62 } 63 //初始化哈夫曼编码?!生成哈夫曼编码 64 void createHuffmanCode(HuffmanTree *huffmantree,HuffmanCode *huffmancode,int n) { 65 int i, start, f; 66 char *cd; 67 int c; 68 huffmancode = (HuffmanCode*)malloc((n + 1) * sizeof(char*));//n个头指针向量 69 cd = (char*)malloc(n * sizeof(char)); 70 cd[n - 1] = '\0';//编码结束符 71 for (i = 1; i <= n; ++i) { 72 start = n - 1; 73 for (c = i, f = (*huffmantree)[i].parent; f != 0; c = f, f = (*huffmantree)[f].parent) { 74 if ((*huffmantree)[f].lchild == c) cd[--start] = '0'; 75 else cd[--start] = '1'; 76 } 77 //为第i个字符编码分配空间 78 huffmancode[i] = (char*)malloc((n - start) * sizeof(char)); 79 strcpy(huffmancode[i], &cd[start]); 80 } 81 free(cd); 82 //开始打印编码 83 cout << "哈夫曼字符 权值 对应编码" << endl; 84 for (i = 1; i <= n; i++) { 85 cout << " " << (*huffmantree)[i].c << " " << (*huffmantree)[i].weight << " " << huffmancode[i] << endl; 86 } 87 //在这里解码,一定要成功!!! 88 string s; 89 cout << "请输入待解码的哈夫曼编码:"; 90 cin >> s; 91 Decode(huffmantree, huffmancode, n, s); 92 } 93 94 string Decode(HuffmanTree *huffmantree,HuffmanCode *huffmancode,int n,string s) { 95 char *c; 96 int i, j, k = 0; 97 for (i = 1; i <= n; i++) { 98 cout << (*huffmantree)[i].c; 99 cout << huffmancode[i] << endl; 100 } 101 c = (char*)malloc(s.size() * sizeof(char));//c的内存空间 102 for (i = 0; i < s.size(); i++) { 103 c[k] = s[i]; 104 c[k + 1] = '\0'; 105 for (j = 1; j <= n; j++) { 106 if (strcmp(c,huffmancode[j])==0) {//找到哈夫曼编码 107 cout << (*huffmantree)[j].c; 108 k = -1; 109 c[0] = '\0'; 110 break; 111 } 112 else if ((i == s.size() - 1) && j == n && c[0] != '\0') cout << "ERROR!!!" << endl; 113 } 114 k++; 115 } 116 return 0; 117 }
调试结果如下:
真的真的是经历了九九八十一难才完成!!!