哈夫曼樹編碼並解碼(加強版)


本代碼流程:

隨機輸入一段字符串--->根據輸入字符串得到每個字符權重(頻數)並輸出--->得到每個字符對應哈夫曼編碼並輸出--->輸入一段哈夫曼編碼--->利用每個字符對應的哈夫曼編碼來解碼

技術支持:

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 }

調試結果如下:

真的真的是經歷了九九八十一難才完成!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM