哈夫曼编码解码(数据结构实验)

哈夫曼树

定义

  • 定义:带权路径长度WPL最小的二叉树称作哈夫曼树,又叫最优二叉树
  • 节点的带权路径长度为:从该节点到树根之间的路径长度与节点上的权的乘积
  • 树的带权路径长度为:所有叶子节点的带权路径长度之和

构造方式

大话数据结构:

  1. 根据给定的n个权值{ w1,w2,w3,···,wn }构成n棵二叉树的集合F = { T1,T2,T3,···,Tn },其中每棵二叉树Ti中只有一个带权为wi的根节点,其左右子树均为空。(其实就是一个节点)
  2. 在F中选取两棵根节点的权值最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根节点的权值为其左右子树上根节点的权值之和。
  3. 在F中删除这两棵树,同时将新得到的二叉树加入F中。
  4. 重复步骤2和3,直到F只含一棵树为止,这棵树便是哈夫曼树。(这个节点便是哈夫曼树的根节点)

举个例子:

哈夫曼编码解码(数据结构实验)

现在有五个字符ABCDE,权值分别为5, 15, 40, 30, 10

先取出权值最小的两个字符,分别为 A, E

将它们作为左右子树构造一棵新的二叉树:

哈夫曼编码解码(数据结构实验)

再将A, E从集合F中删除,将新的得到的N1加入到F中:

N1的权值即为A, E的权值之和:5 + 10 = 15

哈夫曼编码解码(数据结构实验)

重复上述步骤,将权值最小的N1和B作为左右子树构建一棵新的二叉树:

哈夫曼编码解码(数据结构实验)

重复上述步骤,将N2加入到集合F中,将N1和B从集合F中删除,选取F中权值最小的两个节点分别为N2, D构建新的二叉树:

哈夫曼编码解码(数据结构实验)

删除N2, D,添加N3,选取最小的两个节点,C和N3作为左右子树构建二叉树:

哈夫曼编码解码(数据结构实验)

这样,就完成了哈夫曼树的构造,可以算得:

(WPL = 5 * 3 + 15 * 3 + 40 * 2 + 30 * 2 + 10 * 2 = 220)

哈夫曼编码

将字符的频率作为权值来构建好的哈夫曼树,规定左分支为 0,右分支为 1,则从根节点到叶子节点所经过的路径分支组成的 01序列便为该节点对应字符的编码,这就是哈夫曼编码

将上述的哈夫曼树作为例子,设我们要传输的信息就只有ABCDE这五个字符。

设字符A的频率为5%,B为15%,C为40%,D为30%,E为10%。

假设我们不用哈夫曼编码,很自然的想到,我们用二进制来表示这5个字符:

哈夫曼编码解码(数据结构实验)

现在有一段文本内容:CADECDDBACE

二进制表示:010000011100010011011001000010100

哈夫曼编码:01000111001000101100001001

很明显,用哈夫曼编码传送数据,节约了存储。

若编码为长短不等,那么必须任一字符的编码都不是另一个字符的编码的前缀,这种编码叫前缀编码。
仔细观察就会发现,哈夫曼编码不会出现混淆的情况,这是因为每个字符都是在树上的叶子节点上。

实验

实验简介

实验项目: 树形结构及其应用

实验题目: 哈夫曼编码与译码方法

实验内容:
哈夫曼编码是一种以哈夫曼树(最优二叉树,带权路径长度最小的二叉树)为基础变长编码方法。其基本思想是:将使用次数多的代码转换成长度较短的编码,而使用次数少的采用较长的编码,并且保持编码的唯一可解性。在计算机信息处理中,经常应用于数据压缩。是一种一致性编码法(又称”熵编码法”),用于数据的无损压缩。要求实现一个完整的哈夫曼编码与译码系统。

实验要求:

  1. 从文件中读入任意一篇英文文本文件,分别统计英文文本文件中各字符(包括标点符号和空格)的使用频率;
  2. 根据已统计的字符使用频率构造哈夫曼编码树,并给出每个字符的哈夫曼编码(字符集的哈夫曼编码表);
  3. 将文本文件利用哈夫曼树进行编码,存储成压缩文件(哈夫曼编码文件);
  4. 计算哈夫曼编码文件的压缩率;
  5. 将哈夫曼编码文件译码为文本文件, 并与原文件进行比较。

测试结果

test.txt 英文文本测试文件 test_Copy.txt 英文文本解码文件

code.txt 哈夫曼编码文件 huffman.txt 哈夫曼树的结构文件

test.hfm 哈夫曼压缩文件

关于压缩

就是将文本转换后的哈夫曼编码每一条首尾相连,然后每八位,也就是一个字节,转换为一个字符(但并不是字符,只是为了放到char型变量中),然后以二进制形式存储到文件中。
字符在文本文件中存储的是一字节,8位,对应的是ASCII码。这样压缩后,压缩率就可以得出一个理论计算公式: 压缩率 = 哈夫曼编码长度 / (8 * 文本字符数)。
但实际上,最后不足8位的,我们需要补上,凑一个8位然后存储。

哈夫曼树的结构

struct TreeNode{
    int weight;//权值,这里存储字符出现次数
    char ch;//存储的字符

    TreeNode* left;//左儿子,右儿子,二叉树结构
    TreeNode* right;
};
typedef TreeNode* Huff;

手写堆的结构

/*哈夫曼树的构建过程是每次取最小,然后再放入的过程,这就可以用堆来实现*/
struct HeapNode{
    Huff* data;//直接用数组模拟的堆
    int size;// 堆的大小
    int cap; //容量
};
typedef HeapNode* Heap;

编码表

const int N = 128;
int cnt[N];//字符出现次数
map mp;//使用STL的映射存储

一开始,只需要test.txt,内容如下

Hello,I am Az1r!

I come from China.

Now I am a student,and I major in Computer Science.

编码,译码:

哈夫曼编码解码(数据结构实验)

代码

点击查看代码

/*
    Author: Az1r
    Date: 2022/10/14
*/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <limits>
#include <queue>
#include <map>
#include <fstream>
#include <iomanip>

#define MAX_LENTH 100

using namespace std;

// &#x54C8;&#x592B;&#x66FC;&#x6811;
struct TreeNode{
    int weight;
    char ch;

    TreeNode* left;
    TreeNode* right;
};
typedef TreeNode* Huff;

// &#x5C0F;&#x6839;&#x5806;
struct HeapNode{
    Huff* data;
    int size;// &#x5806;&#x7684;&#x5927;&#x5C0F;
    int cap; //&#x5BB9;&#x91CF;
};
typedef HeapNode* Heap;
Huff T = NULL;

//&#x7F16;&#x7801;&#x8868;
const int N = 128;
int cnt[N];
map<int, string> mp;
int codelenth; //&#x7F16;&#x7801;&#x957F;&#x5EA6;

Huff CreateNode(char ch, int weight);   //&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x54C8;&#x592B;&#x66FC;&#x6811;&#x7684;&#x8282;&#x70B9;
Heap CreateHeap();                      //&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x5C0F;&#x6839;&#x5806;
void InitHeap(Heap H);                  //&#x521D;&#x59CB;&#x5316;&#x5806;
void SetHeap(Heap H, int p);            //&#x5411;&#x4E0B;&#x8C03;&#x6574;&#x5806;
bool IsFull(Heap H);                    //&#x5224;&#x6EE1;
bool IsEmpty(Heap H);                   //&#x5224;&#x7A7A;
bool InsertHeap(Heap H,Huff tree);      //&#x5411;&#x5806;&#x4E2D;&#x63D2;&#x5165;&#x63D2;&#x5165;
Huff Pop(Heap H);                       //&#x5F39;&#x51FA;&#x5806;&#x4E2D;&#x6839;&#x8282;&#x70B9;
void LoadTreeByInput();                 //&#x901A;&#x8FC7;&#x8F93;&#x5165;&#x521D;&#x59CB;&#x5316;&#x54C8;&#x592B;&#x66FC;&#x6811;
Huff BuildHuffmanTree(Heap H);          //&#x5EFA;&#x7ACB;&#x54C8;&#x592B;&#x66FC;&#x6811;
void PrintTree(Huff tree);              //&#x6253;&#x5370;&#x54C8;&#x592B;&#x66FC;&#x6811;
void Menu();                            //&#x6253;&#x5370;&#x83DC;&#x5355;
void CreateDict(Huff tree, string temp);//&#x521B;&#x5EFA;&#x54C8;&#x592B;&#x66FC;&#x7F16;&#x7801;&#x8868;
void PrintCode();                       //&#x6253;&#x5370;&#x7F16;&#x7801;&#x8868;
void LoadTreeByFile();                  //&#x6587;&#x4EF6;&#x8F93;&#x5165;&#x54C8;&#x592B;&#x66FC;&#x6811;
void CodeFile();                        //&#x7F16;&#x7801;&#x6587;&#x672C;&#x6587;&#x4EF6;
void Caulcute();                        //&#x8BA1;&#x7B97;&#x538B;&#x7F29;&#x7387;
void DecodeFile(Huff tree);             //&#x89E3;&#x7801;&#x6587;&#x672C;&#x6587;&#x4EF6;

/*
    test.txt        &#x82F1;&#x6587;&#x6587;&#x672C;&#x6D4B;&#x8BD5;&#x6587;&#x4EF6;
    test_Copy.txt   &#x82F1;&#x6587;&#x6587;&#x672C;&#x89E3;&#x7801;&#x6587;&#x4EF6;
    code.txt        &#x54C8;&#x592B;&#x66FC;&#x7F16;&#x7801;&#x6587;&#x4EF6;
    huffman.txt     &#x54C8;&#x592B;&#x66FC;&#x6811;&#x7684;&#x7ED3;&#x6784;&#x6587;&#x4EF6;
    test.hfm        &#x54C8;&#x592B;&#x66FC;&#x538B;&#x7F29;&#x6587;&#x4EF6;
*/
int main()
{
    int select = -1;
    while(select)
    {
        system("pause");
        system("cls");
        Menu();
        printf("input your choose: ");
        scanf("%d", &select);

        switch(select)
        {
            case 1:
            {
                PrintTree(T);
                break;
            }
            case 2:
            {
                DecodeFile(T);
                break;
            }
            case 3:
            {
                CodeFile();
                break;
            }
            case 4:
            {
                PrintCode();
            }
            case 5:
            {
                Caulcute();
                break;
            }
            case 0:
            {
                break;
            }
            default:
            {
                break;
            }
        }
    }
    return 0;
}

void Menu()
{
    printf("----         Menu         ----");   printf("\n");
    printf("----    1.PrintTree       ----");   printf("\n");
    printf("----    2.Decode          ----");   printf("\n");
    printf("----    3.Code            ----");   printf("\n");
    printf("----    4.PrintDictCode   ----");   printf("\n");
    printf("----    5.Caulcute        ----");   printf("\n");
    printf("----    0.Exit            ----");   printf("\n");

}
void Caulcute()
{
    int chTotal = 0;
    int hfmTotal = 0;
    for(int i = 0; i < N; i ++ )
    {
        chTotal += cnt[i];
        hfmTotal += cnt[i] * mp[i].length();
    }
    if(hfmTotal % 8 == 0)
    {
        hfmTotal /= 8;
    }else
    {
        hfmTotal = (hfmTotal + 8) / 8;
    }
    double rate = hfmTotal * 1.0 / chTotal  * 100; //1&#x4E2A;&#x5B57;&#x7B26;&#x5360;8&#x4F4D;
    cout << "Code rate: " << rate << "%" << "\n";
}
void DecodeFile(Huff tree)
{
    ifstream inbfile; //&#x4E8C;&#x8FDB;&#x5236;&#x8BFB;&#x53D6;
    inbfile.open("test.hfm", ios::in | ios::binary);

    ofstream outfile;
    outfile.open("test_Copy.txt");

    if(inbfile == NULL || outfile == NULL)
    {
        printf("File open error!\n");
        return;
    }

    unsigned char temp;
    Huff x = tree;

    while(!inbfile.eof())
    {
        inbfile.read((char *)&temp, sizeof (unsigned char));
        if(inbfile.fail())//&#x9632;&#x6B62;&#x8BFB;&#x5230;&#x6700;&#x540E;
        {
            break;
        }

        for(int i = 0; i < 8; i++ )
        {
            int j = 7 - i;

            if(codelenth == 0)
            {
                break;
            }

            codelenth --;
            if( (temp >> j) & 1)
            {
                x = x->right;
            }else
            {
                x = x->left;
            }
            if(x->left == NULL && x->right == NULL) // &#x5DE6;&#x53F3;&#x513F;&#x5B50;&#x90FD;&#x65E0;&#xFF0C;&#x90A3;&#x5C31;&#x662F;&#x53F6;&#x5B50;&#x8282;&#x70B9;&#xFF0C;&#x5373;&#x4FDD;&#x5B58;&#x5B57;&#x7B26;&#x7684;&#x8282;&#x70B9;
            {
                outfile << x->ch;
                x = tree;
            }
        }
    }

    inbfile.close();
    outfile.close();
    printf("Succeeful decode file!\n");
    printf("Succeeful generate test_Copy.txt!\n");
}
void CodeFile()
{
    for(int i = 0; i < N; i ++ )
    {
        cnt[i] = 0;
    }
    ifstream infile;
    infile.open("test.txt");

    if(infile == NULL)
    {
        printf("Open file error!\n");
        return;
    }

    infile >> noskipws; //  &#x63A7;&#x5236;&#x7B26;&#xFF0C;&#x53EF;&#x4EE5;&#x8BFB;&#x53D6;&#x7A7A;&#x683C;&#x56DE;&#x8F66;

    char ch;
    while(!infile.eof())
    {
        infile >> ch;

        if(infile.fail())//&#x9632;&#x6B62;&#x8BFB;&#x5230;&#x6700;&#x540E;&#x4E00;&#x4E2A;&#x5B57;&#x7B26;
        {
            break;
        }
        cnt[(int)ch] ++;
    }
    infile.close();

    ofstream outfile;
    outfile.open("huffman.txt");

    if(outfile == NULL)
    {
        printf("Open file error!\n");
        return;
    }

    for(int i = 0; i < N; i ++ )
    {
        if(cnt[i])
        {
            ch = i;
            outfile << ch << cnt[i] << "\n"; //&#x8F93;&#x51FA;&#x5230;&#x54C8;&#x592B;&#x66FC;&#x6811;&#x7ED3;&#x6784;&#x6587;&#x4EF6;&#x4E2D;
        }
    }
    outfile.close();

    LoadTreeByFile();
    CreateDict(T, "");

    infile.open("test.txt");
    infile >> noskipws;
    outfile.open("code.txt");

    ofstream bfile;
    bfile.open("test.hfm", ios::out | ios::binary);

    if(outfile == NULL || infile == NULL || bfile == NULL)
    {
        printf("Open file error!\n");
        return;
    }

    int bitflag = 0;
    unsigned char res = 0;
    while(!infile.eof())
    {
        infile >> ch;
        if(infile.fail())//&#x9632;&#x6B62;&#x8BFB;&#x5230;&#x6700;&#x540E;&#x4E00;&#x4E2A;&#x5B57;&#x7B26;
        {
            break;
        }

        string temp = mp[(int)ch];
        outfile << temp;

        int templenth = temp.length();

        for(int i = 0; i < templenth; i ++ )
        {
            codelenth ++;
            bitflag ++;
            res <<= 8 1; if(temp[i]="=" '1') { res |="1;" } if(bitflag="=" 8) bitflag="0;" bfile.write((char *)&res, sizeof (unsigned char)); if(bitflag) for(int i="0;" < - ;i ++) <<="1;" infile.close(); outfile.close(); bfile.close(); printf("succeeful code file!\n"); generate huffman.txt, code.txt, test.hfm !\n"); void printcode() int total="0;" n; ++ ) +="cnt[i];" 输出字符,频率,编码 if(cnt[i]) float f="cnt[i]" * 1.0 total; if(i="=" 10) cout setw(3) "---- " "\\n" ---- fixed setprecision(3) mp[i] "\n" ; }else if (i="=" 32) "<space>" << " ---- " << fixed << setprecision(3) << f << "  " << mp[i] << "\n" ;
            }else
            {
                cout << setw(3)  << i << "---- " << (char)i << "       ---- " << fixed << setprecision(3) << f << "  " << mp[i] << "\n" ;
            }
        }
    }
}
void CreateDict(Huff tree, string temp)
{
    if(tree)
    {
        if(tree->left == NULL && tree->right == NULL)
        {
            int idx = tree->ch;
            mp[idx] = temp;
        }else
        {
            CreateDict(tree->left, temp + "0");//&#x5DE6; 0
            CreateDict(tree->right, temp + "1");//&#x53F3; 1
        }
    }
}

Huff CreateNode(char ch, int weight)
{
    Huff Node = (Huff)malloc(sizeof (TreeNode));

    Node->ch = ch;
    Node->weight = weight;
    Node->left = Node->right = NULL;
    return Node;
}
// &#x5806;&#x7684;&#x6784;&#x5EFA;
Heap CreateHeap()
{
    Heap Node = (Heap)malloc(sizeof (HeapNode));

    Node->data = (Huff *)malloc((MAX_LENTH + 1) * sizeof (Huff));
    Node->size = 0;
    Node->cap = MAX_LENTH;
    Node->data[0] = CreateNode('\0',INT_MIN);

    return Node;
}

// &#x5806;&#x7684;&#x5411;&#x4E0B;&#x8C03;&#x6574;
void SetHeap(Heap H, int p)
{
    int parent, child;
    int lenth = H->size;

    Huff root = H->data[p];

    for(parent = p; parent * 2 <= lenth; parent="child)" { 将child指向parent的左右子节点中最小者 child="parent" * 2; if((child < lenth) && h->data[child]->weight > H->data[child + 1]->weight){
            child++;
        }
        // &#x5982;&#x679C;child&#x7684;&#x6743;&#x91CD;&#x4E0D;&#x518D;&#x5C0F;&#x4E8E;parent,&#x8C03;&#x6574;&#x5B8C;&#x6BD5;,&#x5426;&#x5219;&#x7EE7;&#x7EED;&#x8FDB;&#x884C;&#x8C03;&#x6574;
        if(root->weight <= h->data[child]->weight)
        {
            break;
        }else
        {
            H->data[parent] = H->data[child];
        }
    }
    H->data[parent] = root;

}
// &#x521D;&#x59CB;&#x5316;&#x6700;&#x5C0F;&#x5806;
void InitHeap(Heap H)
{
    // &#x4ECE;&#x6700;&#x540E;&#x4E00;&#x4E2A;&#x8282;&#x70B9;&#x7684;&#x7236;&#x8282;&#x70B9;&#x5F00;&#x59CB;,&#x4E00;&#x76F4;&#x5230;&#x6839;&#x8282;&#x70B9;1 (0&#x662F;&#x54E8;&#x5175;&#x8282;&#x70B9;)
    for(int i = H->size / 2; i > 0; i --)
    {
        SetHeap(H,i);
    }
}
// &#x5224;&#x7A7A;&#xFF0C;&#x5224;&#x6EE1;
bool IsFull(Heap H)
{
    return (H->size == H->cap);
}
bool IsEmpty(Heap H)
{
    return (H->size == 0);
}

// &#x63D2;&#x5165;&#x5806;&#x7684;&#x64CD;&#x4F5C;
bool InsertHeap(Heap H,Huff tree)
{
    if(IsFull(H))
    {
        printf("Full Heap!\n");
        return false;
    }

    H->size ++;
    int i= H->size;
    // i&#x4E3A;&#x6700;&#x540E;&#x4E00;&#x4E2A;&#x4F4D;&#x7F6E;&#xFF0C;&#x7136;&#x540E;&#x4E00;&#x5C42;&#x4E00;&#x5C42;&#x5411;&#x4E0A;&#x8FC7;&#x6EE4;
    for(; H->data[i / 2]->weight > tree->weight; i /= 2)
    {
        H->data[i] = H->data[i / 2];
    }
    H->data[i] = tree;

    return true;
}
// &#x4ECE;&#x5806;&#x4E2D;&#x53D6;&#x51FA;&#x6700;&#x5C0F;&#x5143;&#x7D20;&#x7684;&#x5B9E;&#x73B0;
Huff Pop(Heap H)
{
    if(IsEmpty(H))
    {
        printf("Empty Heap!\n");
        return NULL;
    }
    int parent,child;
    int lenth = H->size;
    // &#x53D6;&#x51FA;&#x6839;&#x8282;&#x70B9;
    Huff rootTree = H->data[1];
    // xTree&#x4E3A;&#x6700;&#x540E;&#x4E00;&#x4E2A;&#x5143;&#x7D20;&#xFF0C;&#x540C;&#x65F6;size-1&#xFF08;&#x56E0;&#x4E3A;&#x53D6;&#x51FA;&#x4E86;&#x6839;&#x8282;&#x70B9;&#xFF09;
    Huff xTree = H->data[H->size --];
    // &#x4ECE;&#x6839;&#x8282;&#x70B9;&#x4E0B;&#x9762;&#x627E;&#x51FA;&#x6700;&#x5C0F;&#x7684;&#x66FF;&#x6362;&#x4E0A;&#x6765;
    for(parent = 1;parent * 2 <= lenth; parent="child)" { child="parent" * 2; if((child < lenth) && (h->data[child]->weight > H->data[child+1]->weight))
        {
            child ++;
        }
        if(xTree->weight <= h->data[child]->weight)
        {
            break;
        }else
        {
            H->data[parent] = H->data[child];
        }
    }
    H->data[parent] = xTree;

    return rootTree;
}

// &#x54C8;&#x592B;&#x66FC;&#x6811;&#x7684;&#x6784;&#x9020;
Huff BuildHuffmanTree(Heap H)
{
    // &#x5047;&#x8BBE;&#x5DF2;&#x7ECF;&#x65E0;&#x5E8F;&#x7684;&#x5C06;&#x8282;&#x70B9;&#x4FDD;&#x5B58;&#x5728;&#x5806;&#x7684;data&#x4E2D;,
    // &#x9996;&#x5148;&#x8981;&#x5C06;&#x5806;&#x8C03;&#x6574;&#x4E3A;&#x6700;&#x5C0F;&#x5806;
    Huff tree;
    InitHeap(H);
    int size = H->size;
    for(int i = 1;i < size; i ++)
    {
        tree = (Huff)malloc(sizeof (TreeNode));
        // &#x53D6;&#x51FA;&#x4E24;&#x4E2A;&#x6700;&#x5C0F;&#x8282;&#x70B9;&#xFF0C;&#x4F5C;&#x4E3A;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x7684;&#x5DE6;&#x53F3;&#x5206;&#x652F;
        tree->ch = '\0';
        tree->left = Pop(H);
        tree->right = Pop(H);
        // &#x8BA1;&#x7B97;&#x65B0;&#x7684;&#x6743;&#x503C;
        tree->weight = tree->left->weight + tree->right->weight;
        // &#x5C06;&#x8FD9;&#x4E2A;&#x8282;&#x70B9;&#x518D;&#x63D2;&#x5165;&#x6700;&#x5C0F;&#x5806;
        InsertHeap(H,tree);

        /* test

        */
    }
    // &#x53D6;&#x51FA;&#x54C8;&#x592B;&#x66FC;&#x6811;&#x6839;&#x8282;&#x70B9;(&#x4E5F;&#x5C31;&#x662F;&#x5806;&#x9876;&#x8282;&#x70B9;)
    tree = Pop(H);
    return tree;
}
// &#x5148;&#x5E8F;&#x904D;&#x5386;&#x54C8;&#x592B;&#x66FC;&#x6811;
void PrintTree(Huff tree)
{
    if(tree)
    {
        if((tree->left == NULL) && (tree->right == NULL))
        {
            char ch = tree->ch;
            if(ch == '\n')
            {
                cout << "Leaf  " << setw(3) << tree->weight << " ---- " << "\\n" << "\n" ;
            }else if(ch == ' ')
            {
                cout << "Leaf  " << setw(3) << tree->weight << " ---- " << "<space>" << "\n" ;
            }else
            {
                cout << "Leaf  " << setw(3) << tree->weight << " ---- " << ch << "\n" ;
            }
        }else
        {
            cout << "Node  " << setw(3) << tree->weight << "\n" ;
        }
        PrintTree(tree->left);
        PrintTree(tree->right);
    }
}
void LoadTreeByFile()
{
    ifstream infile;
    infile.open("huffman.txt");
    if(infile == NULL)
    {
        printf("load file error!\n");
        return;
    }
    int weight;
    char ch;
    char temp[20];

    Heap heap = CreateHeap();

    infile >> noskipws; //  &#x63A7;&#x5236;&#x7B26;&#xFF0C;&#x53EF;&#x4EE5;&#x8BFB;&#x53D6;&#x7A7A;&#x683C;&#x56DE;&#x8F66;
    while(!infile.eof())
    {
        infile >> ch;
        infile.getline(temp, 20);
        weight = atoi(temp);

        heap->data[++ heap->size] = CreateNode(ch, weight);
    }
    infile.close();
    T = BuildHuffmanTree(heap);
}
// &#x54C8;&#x592B;&#x66FC;&#x6811;&#x4ECE;&#x7528;&#x6237;&#x8F93;&#x5165;
void LoadTreeByInput()
{
    printf("please input your haffman:\n");
    int weight,count;
    char ch;
    char temp[10];

    Heap heap = CreateHeap();
    printf("input data num :");
    scanf("%d", &count);
    cout << "( data+weight ):" <<endl; for(int i="1;i" <="count;" ++) { scanf("%s", temp); ch="temp[0];" weight="atoi(temp" + 1); cnt[(int)ch]="weight;" heap->data[i] = CreateNode(ch, weight);
        heap->size ++;
    }
    T = BuildHuffmanTree(heap);
}
</endl;></space></=></=></=></=></=></int,></iomanip></fstream></map></queue></limits></cstdio></cstring></iostream>

一些相关的问题

  1. 代码中的堆,是手写的小根堆,也可以使用STL中优先队列priority_queue来实现。
  2. 上述 1-5 的编码和译码是基于字符的压缩,如何考虑基于单词的压缩,完成上述工作。
  3. 上述 1-5 的编码是二进制的编码,如何采用 K 叉的哈夫曼树完成上述工作,实现”K 进制”的编码和译码 。

参考资料

  1. 程杰. 大话数据结构:溢彩加强版[M]. 北京: 清华大学出版社, 2020.

  2. [数据结构] 使用最小堆思想实现哈夫曼编解码

Original: https://www.cnblogs.com/Az1r/p/16794068.html
Author: 江水为竭
Title: 哈夫曼编码解码(数据结构实验)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/685477/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球