哈夫曼树编码并解码(加强版)

本代码流程:

随机输入一段字符串--->根据输入字符串得到每个字符权重(频数)并输出--->得到每个字符对应哈夫曼编码并输出--->输入一段哈夫曼编码--->利用每个字符对应的哈夫曼编码来解码

技术支持:

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 }

调试结果如下:

真的真的是经历了九九八十一难才完成!!!

posted @ 2020-05-16 21:29  打不死的小王  阅读(1492)  评论(0编辑  收藏  举报