哈夫曼编/译码系统的设计与实现

问题描述

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(解码)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站设计一个哈夫曼编译码系统。

基本要求

  1. 初始化(Initialzation)。从数据文件DataFile.data中读入字符及每个字符的权值,建立哈夫曼树HuffTree;
  2. 编码(EnCoding)。用已建好的哈夫曼树,对文件ToBeTran.data中的文本进行编码形成报文,将报文写在文件Code.txt中
  3. 译码(Decoding)。利用已建好的哈夫曼树,对文件CodeFile.data中的代码进行解码形成原文,结果存入文件Textfile.txt中
  4. 输出(Output)。输出DataFile.data中出现的字符以及各字符出现的频度(或概率);输出ToBeTran.data及其报文Code.txt;输出CodeFile.data及其原文Textfile.txt

大致过程

  1. 首先需要写好哈夫曼树的建立和编码过程
  2. 其次对于译码,则可以从文件中一次读取一个单词,然后挨个完成译码。分别输出到文件。
  3. 对于解码,一次读一个单词的哈夫曼码,依次和之前编好的哈夫曼码进行匹配,直到全部解码完成

    数据结构

哈夫曼树节点

typedef struct {
    int weight;
    int parent,lchild,rchild;
}HufNode;

初始节点

typedef struct {
    int weight;
    char data;
    char code[maxn];//需要被建树的信息
}HufCode;

程序模块

(1) 初始化输入数据

void Init(HufCode h[])//初始化输入数据
{
    FILE *f1=fopen("DataFile.data","r");
    for(int i=0;i<alphanumber;++i)
        fscanf(f1,"%c%d ",&h[i].data,&h[i].weight);

    fclose(f1);
}

(2) 根据数据建立哈夫曼树及将编码保存

void HuffmanTree(HufCode *h2,HufNode *h1,int n)
{
    char str[maxn];
    int m=2*n-1;
    for(int i=0;i<m;++i){
        if(i<n)//前n个全部是叶子节点,
            h1[i].weight=h2[i].weight;
        else//后面的是还没建成的树
            h1[i].weight==0;
        h1[i].lchild=h1[i].parent=h1[i].rchild=0;
    }
    int s1,s2;
    for(int i=n;i<m;++i){
        select(h1,i,s1,s2);
        h1[s1].parent=i;//建立二叉树
        h1[s2].parent=i;
        h1[i].lchild=s1;
        h1[i].rchild=s2;
        h1[i].weight=h1[s1].weight+h1[s2].weight;
    }
    str[n]='\0';
    int l;
    for(int i=0;i<n;++i){
  //从每个叶子节点开始倒序遍历
        l=n-1;//倒序赋值字符串
        for(int k=i,p=h1[k].parent;p;k=p,p=h1[k].parent){
  //沿着叶子回溯到根节点
            if(k==h1[p].lchild)
                str[l]='0';
            else
                str[l]='1';
            l--;
        }
        strcpy(h2[i].code,str+l+1);
       // printf("%c %s\n",h2[i].data,h2[i].code);
    }
}

(3) 根节点中选择两个最小的根

void select(HufNode *h,int k,
  • 20
    点赞
  • 114
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值