哈夫曼编码

一、目标与要求

一:程序的设计内容

                从文件中读入一个英文文本文件(大于2048个字符)

                采用统计字符出现的频率;

                采用哈夫曼编码方法生成编码表

利用此编码表对文件进行压缩编码,保存到文件,同时存入编码表

读入编码文件和编码表,进行解码后保存到文件中,与原始文件进行对比

二:基本要求

                完成文本文件的读写操作;

                编写通用的树(使用模板类);

                生成哈夫曼树;

三:分析程序及实验方法

二、工具/准备工作

VC6.0,节点类、串类、链表类、树结点类软件包

三、实验分析

首先构建哈夫曼树类

成员变量有:

HuffmanTreeNode<WeightType> *nodes;

CharType *str;                 //存放字符    

String *LeafCharCodes;//存放叶子编码

int num;                   //总结点数,2n-1

int n;                 //叶子结点数,n

int curpos;         //译码时路径点

成员函数有:

void Select(int cur, int &r1, int &r2); //选择没有父母的权最小的两个结点

HuffmanTree(CharType *ch,WeightType *w,int n);//构造函数

~HuffmanTree();                                          //析构函数

String Encode(CharType ch);                                //辅助编码

LinkList<CharType> Decode(String strCode); //译码

主程序中,先构建统计字符频率的函数,根据具体文本生成相应的哈夫曼树。

之后将文本编码、连同权重等信息保存至文件。

最后读取编码文件及权重文件,生成哈夫曼树,利用生成的哈夫曼树解码,将解出的文件与原文本比对。

四、实验步骤

1.引入相关函数包,编写huffman_tree类。

编码时,字符的编码就是从根结点到该叶子结点的路径码,左为0右为1,具体操作时可以从叶子结点出发回到根结点,如果结点是双亲的左孩子,则在编码链表最前端插入0,否则插入1。

解码时需要借助哈夫曼树,其过程是:依次读入编码,从哈夫曼树的根结点出发,若当前读入0,则走向左孩子,否则走向右孩子。当到达某一叶子结点时便译出相应的字符。然后重新从根结点出发继续译码,直至文件结束。

2.完成统计字符频率sort函数的编写

3.利用权值表生成哈夫曼树,压缩编码并保存到文件

4.读取文件,生成哈夫曼树进行解码,将解码后的文章与原文比对,调试完善程序

五、测试与结论

原文本:

编码后的文件:

字符及权值表:

解码后的文本:与原文本相同

六、实验总结

1. 本次实验实现了将文章编码、解码的功能,但存放01代码时没有逐个bit存储,而是把’0’’1’当做一个字符,这一点做得不是很好;

2. 独立编写了哈夫曼树类,编写时虽然思路清楚,但很容易出现问题,比如弄错下标等等,编程能力还需进一步提高。

具体代码:

#include"utility.h"
#include"huffman_tree.h"
//#include"huffman_tree_node.h"
//#include"node.h"
//#include"string.h"
#include "lk_list.h"

void sort(char str[],int a[])    //统计字符频率
{int t;
    for(int i=0;i<strlen(str);i++)
    if(96<str[i]&&str[i]<123)            //数组a的前0-25位放'a'至'z'频率
    {t=str[i]-'a';
     a[t]++;
    }
    else if(str[i]==' ')        //数组a的第26位放空格符频率
    {a[26]++;
    }
    else if(64<str[i]&&str[i]<91)        //数组a的27-52位放'A'-'Z'频率
    {t=str[i]-'A'+27;
    a[t]++;}
    else if(str[i]==',')
    {a[53]++;}
    else if(str[i]=='.')
    {a[54]++;}
    else if(str[i]=='?')
    {a[55]++;}
    else if(str[i]=='(')
    {a[56]++;}
    else if(str[i]==')')
    {a[57]++;}
    else if(str[i]=='-')
    {a[58]++;}
    else if(str[i]=='\'')
    {a[59]++;}
    else cout<<"遇到无法识别的字符!"<<endl;
}

void main()
{char str[]="abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ,.?()!\'";
int a[60]={0},i=0;
char b[3000];

ifstream infile("text.txt");    
infile.getline(b,3000);
infile.close();
sort(b,a);    //得到权值表

HuffmanTree<char,int> tree(str,a,60);

String tcode;
const char *p;

ofstream outfile("tcode.txt");    
for(i=0;i<strlen(b);i++)    
{tcode=tree.Encode(b[i]);
p=tcode.CStr(); 
outfile<<p;
}       
outfile.close();    //将转码存入"tcode.txt"
    
ofstream outfile2("mcode.txt");
outfile2<<str;
for(i=0;i<60;i++)
{outfile2<<a[i]<<'\t';
}
outfile2.close();//将字符及频率存入编码表,便于解码时生成相应的哈夫曼树

//以下为解码操作
char list[61];
int listf[60];
LinkList<char> texth;
ifstream infile2("mcode.txt");
infile2.getline(list,61);
for(i=0;i<60;i++)
{infile2>>listf[i];
}
infile2.close();
HuffmanTree<char,int> T(list,listf,60);


//cout<<list<<endl;

char t1[10000];
ifstream infile3("tcode.txt");
infile3.getline(t1,9999);
infile3.close();                

const char *t2;
t2=t1;
String ff(t2);
texth=T.Decode(ff);
ofstream outfile3("testnew.txt");    //将解出的字符写入testnew.txt
char tt;
for(int j=1;j<texth.Length()+1;j++)
    {texth.GetElem(j,tt);
    outfile3<<tt;
    }
outfile3.close();

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

金锋986321

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值