本代碼流程:
隨機輸入一段字符串--->根據輸入字符串得到每個字符權重(頻數)並輸出--->得到每個字符對應哈夫曼編碼並輸出--->輸入一段哈夫曼編碼--->利用每個字符對應的哈夫曼編碼來解碼
技術支持:
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 }
調試結果如下:
真的真的是經歷了九九八十一難才完成!!!