哈夫曼编码译码系统Word文档格式.docx
《哈夫曼编码译码系统Word文档格式.docx》由会员分享,可在线阅读,更多相关《哈夫曼编码译码系统Word文档格式.docx(20页珍藏版)》请在冰豆网上搜索。
然后根据data属性按从小到大顺序排序,每次从data取出两个最小和此次小的HTNode,将他们的data相加,构造出新的HTNode作为他们的父节点,指针parent,leftchild,rightchild赋相应值。
在把这个新的节点插入最小堆。
按此步骤可以构造构造出一棵哈夫曼树。
通过已经构造出的哈夫曼树,自底向上,由频率节点开始向上寻找parent,直到parent为树的顶点为止。
这样,根据每次向上搜索后,原节点为父节点的左孩子还是右孩子,来记录1或0,这样,每个频率都会有一个01编码与之唯一对应,并且任何编码没有前部分是同其他完整编码一样的。
3、实验步骤
先统计要压缩编码的文件中的字符字母出现的次数,按字符字母和空格出现的概率对其进行哈夫曼编码。
然后读入要编码的文件,编码后存入另一个文件;
接着再调出编码后的文件,并对其进行译码输出,最后存入另一个文件中。
具体步骤:
1.初始化,统计文本文件中各字符的个数作为权值,生成哈夫曼树;
2.根据符号概率的大小按由大到小顺序对符号进行排序;
3.把概率最小的两个符号组成一个节点;
4.重复步骤2.3,直到概率和为1;
5.从根节点开始到相应于每个符号的“树叶”,概率大的标“0”,概率小的标“1”;
6.从根节点开始,对符号进行编码;
7.译码时流程逆向进行,从文件中读出哈夫曼树,并利用哈夫曼树将编码序列解码。
四、实验结果与分析
哈夫曼编码是动态变长编码,临时建立概率统计表和编码树。
概率小的码比较长,概率小的码比较长。
概率大的码短,这样把一篇文件编码后,就会压缩许多。
从树的角度看,哈夫曼编码方式是尽量把短码都利用上。
首先,把一阶节点全都用上,如果码字不够时,然后,再从某个节点伸出若干枝,引出二阶节点作为码字,以此类推,显然所得码长最短,再根据建立的概率统计表合理分布和放置,使其平均码长最短就可以得到最佳码。
实验截图:
五、实验心得
本次实验结合了之前所学的赫夫曼算法,并利用其原理实现赫夫曼编码/译码系统;
实验难度较之前的几次实验有所增加,所以花了比较多的时间来编写,测试代码。
期间参考了网上的一些程序,通过结合分析,了解其他人在实现这个算法时的思想,也借鉴了其中的一些东西,同时加入了自己的想法。
最终完成饿了本次的作业。
通过这次实验,我了解了一个算法到一个可以执行的程序之间还有很多工作需要做,深刻体会到实践出真知的到了,看似简单的算法在实现时却话费了这么多时间,但是这个过程中也让我学到了很多。
六、主要代码
Huffman_Tree.h:
#ifndefHuffman_Tree_h
#defineHuffman_Tree_h
#endif
#include<
stdio.h>
typedefstruct{
unsignedintweight;
unsignedintparent,lchild,rchild;
}HTNode,*HuffmanTree;
//存储赫夫曼树的结点类型
typedefchar**HuffmanCode;
//用于存储字符集中各个字符相应的赫夫曼编码
voidstrcpy(char*S1,char*S2){//将字符串S2复制到S1
inti=0;
while(S2[i]!
='
\0'
){
S1[i]=S2[i];
i++;
}
S1[i]='
;
}
//在HT[1]到HT[t-1]中找出权值最小的两个S1和S2-----------------------------------------------
voidSelect(HuffmanTreeHT,intt,int&
s1,int&
s2){
inti=1;
s1=s2=0;
HT[0].weight=50000;
while(i<
=t){//遍历查找权值最小的结点S1
if(HT[i].parent==0&
&
HT[i].weight<
HT[s1].weight)
s1=i;
i=1;
=t){//遍历查找除S1外权值最小的结点S2
if(i!
=s1&
HT[i].parent==0&
HT[s2].weight)
s2=i;
//根据各个字符的权值构造赫夫曼树HT,将对应的赫夫曼编码存储在HC中------------------------------------------------
intHuffmanCoding(HuffmanTree&
HT,HuffmanCode&
HC,int*w,intn){
ints1,s2,m,i,start;
unsignedintc,f;
HTNode*p;
char*cd;
if(n<
=1)return0;
m=2*n-1;
//赫夫曼树的总结点树为m
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
//申请存储赫夫曼树的空间
for(p=HT+1,i=1;
i<
=n;
++i,++p,++w){//将各个叶子结点的weight赋以相应的权值,parent,lchild,rchild均赋为0
p->
weight=*(w+1);
parent=p->
lchild=p->
rchild=0;
for(;
=m;
++i,++p){//将各个非叶子结点的weight,parent,lchild,rchild均赋为0
weight=p->
for(i=n+1;
++i){//构造赫夫曼树,给各个非叶子结点赋值
Select(HT,i-1,s1,s2);
HT[s1].parent=i;
HT[s2].parent=i;
HT[i].lchild=s1;
HT[i].rchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
//根据已建立的赫夫曼树对需要编码的字符进行编码----------------------------------------------------------
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));
//用于存储指向存储各个字符相应赫夫曼编码的字符数组的指针
cd=(char*)malloc(n*sizeof(char));
//分配工作所需空间
cd[n-1]='
//编码结束符
for(i=1;
++i)//逐个字符求赫夫曼编码
{
start=n-1;
//编码在数组cd[]中的最前位置
//从叶子到根逆向求编码,初始值;
停止条件;
一次循环后对上一个节点做循环
for(c=i,f=HT[i].parent;
f!
=0;
c=f,f=HT[f].parent)
if(HT[f].lchild==c)
cd[--start]='
0'
else
1'
HC[i]=(char*)malloc((n-start)*sizeof(char));
//为第i个字符编码分配空间
strcpy(HC[i],&
cd[start]);
//将cd[]数组的start位置到n-1位置复制给HC[i]
free(cd);
//释放空间
return1;
Test.cpp:
stdlib.h>
#include"
Huffman_Tree.h"
#defineYes1//当程序已经调用过初始化赫夫曼树的InitHuff_T()函数,或已从htfTree文件读取过,则将Init_Mode置为Yes,否则为No
#defineNo0
voidInitHuff_T(HuffmanTree&
HT,HuffmanCode&
HC,charch[],int&
n){//初始化赫夫曼数,要求用户输入字符和相应权值
inti=1,w[100],temp,j;
chara[20];
//数字转字符时,用于储存赫夫曼编码
FILE*save;
printf("
请输入编码字符集的大小:
"
);
scanf("
%d"
&
n);
//获取用户输入的字符集个数
=n){//获取用户输入的字符和相应权值,分别存储在ch[]和w[]数组中
请输入第%d个字符和该字符的权值:
i);
fflush(stdin);
//刷新标准输入缓冲区,把输入缓冲区里的东西丢弃
%c%d"
ch[i],&
w[i]);
ch[i]='
//哈夫曼树保存--------------------------------------------------------------------------------------------
HuffmanCoding(HT,HC,w,n);
//根据用户的输入,生成赫夫曼数及各个字符相应的赫夫曼编码,分别存在HT树和HC中
if((save=fopen("
hfmTree.TXT"
"
w"
))==NULL){//打开用于存储赫夫曼树的文件
Openfilefail......\n"
exit(0);
temp=n;
//将字符集大小转换成字符形式写入到文件hfmTree.TXT中
j=0;
while(temp!
=0){//计算数字位数
temp=temp/10;
j++;
//数字转字符
a[j]='
=0){
a[j-1]=(char)(temp%10+48);
j--;
fputs(a,save);
%d\n