Huffman文件解码编程实现

问题描述

给定一组字符的Huffman编码表(从标准输入读取),以及一个用该编码表进行编码的Huffman编码文件(存在当前目录下的in.txt中),编写程序实现对Huffman编码文件的解码,并按照前序遍历序列输出解码过程中Huffman树(规定树中左分支表示0,右分支表示1)中各结点的访问次数。

例如给定的一组字符的Huffman编码表为:

6
1:111
2:0
+:110
*:1010
=:1011
8:100

第一行的6表示要对6个不同的字符进行编码,后面每行中冒号(:)左边的字符为待编码的字符,右边为其Huffman编码,冒号两边无空格。对于该编码表,对应的Huffman树(树中左分支表示0,右分支表示1)应为:

huf1.jpg

假如Huffman编码文件in.txt中的内容(由0和1字符组成的序列)为:

111011001010011001011111100

则遍历上述Huffman树即可对该文件进行解码,解码后的文件内容为:

12+2*2+2=18

解码过程中,经过Huffman树中各结点的遍历次数见下图中结点中的数字:

对该Huffman树中各结点的访问次数按照前序遍历序列输出应为:

11 4 7 3 1 2 1 1 4 2 2

【输入形式】

先从标准输入读入待编码的字符个数(大于等于2,小于等于50),然后分行输入各字符的Huffman编码(先输入字符,再输入其编码,字符和编码中间以一个英文字符冒号:分隔),编码只由0和1组成。

Huffman编码文件为当前目录下的in.txt文本文件,即:其中的0和1都是以单个字符的形式存储,文件末尾有一个回车换行符。

【输出形式】

先将解码后的文件内容输出到标准输出上(独占一行);然后以前序遍历序列输出解码过程中Huffman树中各结点的访问次数,各数据间以一个空格分隔,最后一个数据后也有一个空格。

【样例输入】

6
1:111
2:0
+:110
*:1010
=:1011
8:100

假如in.txt中的内容为:

111011001010011001011111100

【样例输出】

12+2*2+2=18
11 4 7 3 1 2 1 1 4 2 2

【样例说明】

从标准输入读取了6个字符的Huffman编码,因为规定Huffman树中左分支表示0,右分支表示1,所以利用该编码表可构造上述Huffman树(见图1)。遍历该Huffman树对编码文件in.txt的进行解码,即可得到解码后的原文件内容,遍历过程中各树中结点的最终访问次数要按照前序遍历序列输出。

给出一些字符的哈夫曼编码之后给你一串乱码将其翻译并输出哈夫曼树中每个节点的访问次数

思路很简单:首先根据字符与01串的对应情况建立一个二叉树,注意这里就是遵循“碰0 lchild 碰1 rchild”的思路去建立二叉树

        if (str[i] == '0')

        {

            if (p->lchild == NULL)//注意这里的判断部分

                p->lchild = new BTNode();

            p = p->lchild;

        }

        else

        {

            if (p->rchild == NULL)

                p->rchild = new BTNode();

            p = p->rchild;

        }

注意这里的判断if左/右孩子为空,应该建立一个左右孩子节点,不然不判断每次都直接建立就会出现有些节点的左右孩子被覆盖的情况,会右意想不到的bug

另外在读取哈夫曼编码时会出现一些判断和循环结构,注意区分每个分支中变量的变化情况,便面陷入死循环中

完整代码如下

#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;

struct BTNode
{
    char data;
    int count;
    BTNode *lchild;
    BTNode *rchild;
    BTNode()
    {
        count = 0;
        lchild = rchild = NULL;
    }
    BTNode(char data)
    {
        count = 0;
        data = data;
        lchild = rchild = NULL;
    }
};
void createBtree(BTNode *root, string str)
{
    BTNode *p = root;
    for (int i = 2; i < str.length(); i++)
    {
        if (str[i] == '0')
        {
            if (p->lchild == NULL)
                p->lchild = new BTNode();
            p = p->lchild;
        }
        else
        {
            if (p->rchild == NULL)
                p->rchild = new BTNode();
            p = p->rchild;
        }
    }
    // 跳出循环
    p->data = str[0];
}

void xian(BTNode *p)
{
    if (p != NULL)
    {
        cout << p->count << " ";
        xian(p->lchild);
        xian(p->rchild);
    }
}
int main()
{
    int num;
    cin >> num;
    ifstream ifs("in.txt");
    string str; // 待解码字符串
    ifs >> str;
    string linestr;
    BTNode *root = new BTNode();
    for (int i = 0; i < num; i++)
    {
        cin >> linestr;

        createBtree(root, linestr);
    }

    int i = 0;

    // 再对读入的str字符串处理
    while (i < str.length())
    {
        BTNode *p = root;
        p->count++;
        while (true)
        {
            if (str[i] == '0')
            {
                if (p->lchild != NULL)
                {
                    p = p->lchild;
                    p->count++;
                    i++;
                }
                else
                {
                    cout << p->data;
                    break;
                }
            }
            else
            {
                if (p->rchild != NULL)
                {
                    p = p->rchild;
                    p->count++;
                    i++;
                }
                else
                {
                    cout << p->data;
                    break;
                }
            }
        }
    }
    cout << endl;

    xian(root);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值