数据结构(哈夫曼编/译码器结构)

该博客介绍了一个完整的哈夫曼编/译码系统的设计,包括统计字符频率、构建哈夫曼树、编码、解码以及打印代码和哈夫曼树的功能。系统针对27个字符的文字进行操作,通过输入文字统计频率,建立哈夫曼树,并对给定报文进行编码和解码测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目4、哈夫曼(Huffman)编/译码器(限1人完成)
【问题描述】
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。首先输入一段包含27个字符(包含空格)的文字(可以存在一个文件中),然后统计出各个字符出现的次数,以每个字符出现的次数为权值构造哈夫曼树,求得哈夫曼编码。
【基本要求】
一个完整的系统应具有以下功能:
1、 O: 输入一段字符(要包含27各字符)存入文件chartexfile中,统计出各个字符出现的次数并以表格的形式存入文件charsumfile中.
例如如下表:

字符 空格 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
频度 186 64 13 22 32 103 21 15 47 57 1 5 32 20 57 63 15 1 48 51 80 23 8 18 1 16 1

2、I:初始化(Initialization)。从终端读入字符集大小n,n个字符及n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
3、 E:编码(Encoding)。利用以建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),
对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
4、D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
5、P:打印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
6、 T:打印哈夫曼树(Tree Printing)。将已在内存中的哈夫曼树以直观的方式(树或凹入
表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
【测试数据】
用文件charsumfile给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。
测试数据要求:
要求使用1、全部合法数据;2、整体非法数据;3、局部非法数据。进行程序测试,以保证程序的稳定

/*
字符集的大小 : 5
字符集(字符集不能重复) : ABCDE
每个字符的权值 : 1 2 3 4 5
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<math.h>
using namespace std;
const int Max=1e5+10;
int m,n;//n是叶子结点,m是所有的节点
char txt[Max];
map<char,int>mp;
struct cmp
{
   
    bool operator()(const pair<int,int> p1, const pair<int,int> p2)
    {
   
        return p1.first > p2.first; //second的小值优先
    }
};
priority_queue<pair<int,int>,vector< pair<int,int> >,cmp > q;
struct HuffmanTree
{
   
    int num;//标记编号
    int val;//权值
    char mark;//该点代表的字符
    int lchild,rchild,parent;
    int pos;//标记位置
    int a;//在二叉树中是第几行
} HT[Max];
struct Code
{
   
    char col[101];//编码的结果
    char mark;//该点代表的字符

} HC[Max];
void CreateHT_Txt(int *cnt)//创建哈夫曼表
{
   
    while(q.size()!=1)
    {
   
        int a,b;
        a=q.top().second;
        q.pop();
        b=q.top().second;
        q.pop();
        HT[++(*cnt)].lchild=a;
        HT[*cnt].rchild=b;
        HT[*cnt].val=HT[a].val+HT[b].val;
        HT[*cnt].num=*cnt;
        HT[a].parent=*cnt;
        HT[b].parent=*cnt;
        q.push(make_pair(HT[*cnt].val,*cnt));
    }
    while(!q.empty())
        q.pop();
}
void CreateHT_Mes()//创建哈夫曼的编码信息
{
   
    char col[100];
    memset(col,0,sizeof(col));
    int f,p,start;
    for(int i=1; i<=n; i++)
    {
   
        start=n-1;
        p=f=i;
        //printf("%d \n",HT[f].parent);
        while(HT[f].parent)
        {
   
            f=HT[f].parent;
            if(p==HT[f].lchild)
                col[start--]='0';
            else if(p==HT[f].rchild)
                col[start--]='1';
            p=f;
        }
        strcpy(HC[i].col,col+start+1);
        HC[i].mark=HT[i].mark;
        //printf("%d %s\n",i,HC[i].col);
        memset(col,0,sizeof(col));
    }
}

void CreateHTree()//操作二
{
   
    memset(HT,0,sizeof(HT));
    memset(HC,0,sizeof(HC));
    m=n=0;
    printf("                       建立哈夫曼树\n\n");
    int len,cnt=0,x,flag=0;
    while(1)
    {
   
        len,cnt=0,x,flag=0;
        while(1)
        {
   
            printf("    请输入字符集的大小,输入-1结束操作:  ");
            scanf("%d",&len);
            if(len==-1)
                break;
            mp.clear();
            getchar();
            printf("    请输入字符集:  ");
            fgets(txt,Max,stdin);
            flag=0;
            cnt=0;
            for(int i=0; i<len; i++)
            {
   
                if(mp[txt[i]]==0)
                {
   
                    mp[txt[i]]=++cnt;
                    HT[cnt].mark=txt[i];
                    HT[cnt].num=cnt;
                }
                else
                {
   
                    printf("        字符集有重复,请重新输入\n\n");
                    mp.clear();
                    memset(HT,0,sizeof(HT));
                    flag=1;
                    break;
                }
            }
            if(flag==0)
                break;
        }
        if(len==-1)
            break;
        printf("    请输入每个字符的权值:  ");
        for(int i=1; i<=cnt; i++)
        {
   
            scanf("%d",&x);
            q.push(make_pair(x,i));
            HT[i].val=x;
        
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值