zoukankan      html  css  js  c++  java
  • 哈夫曼树编码并解码(加强版)

    本代码流程:

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

    技术支持:

    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] = '';//编码结束符
     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] = '';
    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] = '';
    110                 break;
    111             }
    112             else if ((i == s.size() - 1) && j == n && c[0] != '') cout << "ERROR!!!" << endl;
    113         }
    114         k++;
    115     }
    116     return 0;
    117 }

    调试结果如下:

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

  • 相关阅读:
    Redis 主从复制与哨兵
    前端面试中让你困惑的闭包、原型、原型链究竟是什么?
    Chrome V8系列--浅析Chrome V8引擎中的垃圾回收机制和内存泄露优化策略[转]
    nodejs 制作项目目录树代码
    nprogress页面加载进度条
    koa2 从入门到进阶之路 (一)
    原生js 封装好了的ajax 带钩子版本 可封装成对象
    JS
    Javascript面向对象编程(三):非构造函数的继承
    Java 内部类
  • 原文地址:https://www.cnblogs.com/2019-12-10-18ykx/p/12902268.html
Copyright © 2011-2022 走看看