7-2 哈夫曼编码译码 分数 25

编写一个哈夫曼编码译码程序。

按词频从小到大的顺序给出各个字符(不超过30个)的词频,根据词频构造哈夫曼树,给出每个字符的哈夫曼编码,并对给出的语句进行译码。

为确保构建的哈夫曼树唯一,本题做如下限定:

(1)选择根结点权值最小的两棵二叉树时,选取权值较小者作为左子树。

(2)若多棵二叉树根结点权值相等,按先后次序分左右,先出现的作为左子树,后出现的作为右子树。

生成哈夫曼编码时,哈夫曼树左分支标记为0,右分支标记为1。

输入格式:

第一行输入字符个数n;

第二行到第n行输入相应的字符及其词频(可以是整数,与可以是小数);

最后一行输入需进行译码的串。

输出格式:

首先按树的先序顺序输出所有字符的编码,每个编码占一行;

最后一行输出需译码的原文,加上original:字样。

输出中均无空格

输入样例:

3
m1
n1
c2
10110

输出样例:

c:0
m:10
n:11
original:mnc

数据结构实践题目,一道树题,借鉴网友的思路自己写一遍,具体实现看解析了。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<stack>
#include<vector>
#include<cstdlib>
using namespace std;
int N;//字符个数
const int maxn = 1050000;
struct HuffmTree{//哈弗曼树
    char ch;
    double value;
    HuffmTree *left;
    HuffmTree *right;
}tree[maxn];
map<string,char>m;
//词频升序排序
bool Compare(HuffmTree x,HuffmTree y){
        return x.value < y.value;
}
//创建哈弗曼树
HuffmTree* BuildingTree(int N){
    int i = 0,index = N - 1;//i = 0,表示从位置0开始合成,index是生成的节点放置的地方
    while(i < 2*N-1){//while当i没走到最后一个节点就不会停止
        sort(tree+i,tree+index+1,Compare);//排序,找出词频小的两棵子树
        HuffmTree *Node = &tree[i++];//拿出词频最小的两棵子树Node,Node2
        HuffmTree *Node2 = &tree[i++];
        HuffmTree NewNode = tree[index];//中间节点
        NewNode.value = Node->value + Node2->value;//中间节点的权值等于左右节点的权值相加
        NewNode.ch = '.';//设置中间节点的标记
        NewNode.left = Node;//最小的两棵子树被当为左右子树
        NewNode.right = Node2;
        tree[++index] = NewNode;//把新生成的节点加入到结构体数组中
    }
    return &tree[index-1];//返回根节点
}
//先序递归,打印各字符的编码
void PrintCoding(HuffmTree *root,char coding[],int index){
    if(!root) return;//空树返回
    if(root->ch != '.'){//如果是叶子节点
        printf("%c:",root->ch);
        string str = "";
        for(int i = 0;i < index;i++){//打印出该字符的编码
            printf("%d",coding[i]);
            str += to_string(coding[i]);
        }
        printf("\n");
        m[str] = root->ch;
    }
    coding[index] = 0;//左子树设置为0
    index++;//下一个节点
    PrintCoding(root->left,coding,index);//递归访问该节点
    index--;//该节点递归完成,取消该节点的记录
    
    coding[index] = 1;
    index++;//下一个节点
    PrintCoding(root->right,coding,index);//递归访问该节点
    index--;//该节点递归完成,取消该节点的记录
}
//打印译码后的字符串
void PrintDecode(string decoding){
    string str;
    printf("original:");
    for(int i = 0;i < decoding.length();i++){
        str+=decoding[i];//拼接字符对应的编码
        if(m.find(str) != m.end()){//找到了该字符对应的编码
            printf("%c",m[str]);
            str = "";
        }
    }
    printf("\n");
}
int main()
{
    scanf("%d",&N); getchar();
    for(int i = 0;i < N;i++){//输入字符和相应的词频
        scanf("%c%lf",&tree[i].ch,&tree[i].value);
        tree[i].left = NULL;//左右子树为空子树
        tree[i].right = NULL;
        getchar();
    }
    string decoding;//输入需进行译码的串
    cin>>decoding;
    HuffmTree *root = (HuffmTree*)malloc(sizeof(HuffmTree));
    root = BuildingTree(N);//建树
    char coding[1050] = {};//编码字符串,初始化为0
    PrintCoding(root,coding,0);//打印各字符的编码
    PrintDecode(decoding);//打印译码后的字符串
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
[ 问题描述 ] 利用哈夫曼编码进行信息通讯可以大大提高信道利用率, 缩短信息传输时间,降低传输成本。但是, 这要求在发送端通过一个编码系统对待传数据预先编码; 在接收端将传来的数据进行译码( 复原 )。对于双工信道( 即可以双向传输信息的信道 ), 每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编译码系统。 [ 基本要求 ] 一个完整的系统应具有以下功能: (1) I:初始化(Initialization)。从终端读入字符集大小 n,及 n 个字符和 n 个权值,建立哈夫曼树, 并将它存于文件 hfmtree 中。 (2) C:编码(Coding)。利用已建好的哈夫曼树(如不在内存, 则从文件 hfmtree 中读入), 对文件 tobetrans 中的正文进行编码, 然后将结果存入 codefile 中。 (3) D:译码(Decoding)。利用已建好的哈夫曼树将文件 codefile 中的代码进行译码, 结果存入文件 textfile 中。 (4) P:印代码文件(Print)。将文件 codefile 以紧凑格式显示在终端上, 每行 50 个代码。同时将此字符形式的编码文件写入文件 codeprint 中。 (5) T:印哈夫曼树(Tree print)。将已在内存中的哈夫曼树以直观的方式( 树或凹入表行式 )显示在终端上, 同时将此字符形式的哈夫曼树写入文件 treeprint 中。 [ 测试数据 ] (1)利用教科书 6-2 中的数据调试程序。 (2)用下表中给出的字符集和频度的实际统计数据建立哈夫曼树, 并实现以下报 文的编码和译码: "THIS PROGRAM IS MY FAVORITE". 字符 A B C D E F G H I J 频度 186 64 13 22 32 103 21 15 47 57 1 字符 K L M N O P Q R S T U 频度 5 32 20 57 63 15 1 48 51 80 23 字符 V W X Y Z 频度 8 18 1 16 1 [ 实现提示 ] (1) 文件 codefile 的基类型可以设为子界型 bit=0..1。 (2) 用户界面可以设计为"菜单"方式: 显示上述功能符号, 再加上"E",表示结束运行 End, 请用户键入一个选择功能符。此功能执行完毕后再显示此菜单, 直至某次用户选择了 "E"为止。 (3) 在程序的一次执行过程中, 第一次执行 I,D 或 C 命令之后, 哈符曼树已经在内存了, 不必再读入。每次执行中不一定执行 I 命令, 因为文件 hfmtree 可能早己建好。 [ 选作内容 ] (1) 上述 codefile 的基类型实际上占用了存放一个整数的空间, 只起到示意或模拟的作用。现使 codefile 的基类型 package=integer, 把哈夫曼码紧缩到一个整型变量中去, 最大限度地利用码点存储能力, 试改写你的系统。 (2) 修改你的系统, 实现对你的系统的源程序的编码和译码。( 主要是将行尾符编/译码问题 ) (3) 实现各个转换操作的源/目文件, 均由用户在选择此操作时指定。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值