哈夫曼编码报告.docx
《哈夫曼编码报告.docx》由会员分享,可在线阅读,更多相关《哈夫曼编码报告.docx(8页珍藏版)》请在冰豆网上搜索。
哈夫曼编码报告
实验项目:
哈夫曼编码
1・问题描述:
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(解码)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站设
计一个哈夫曼编/译码系统。
2.一个完整的系统应具有以下功能:
1)初始化(Initialzation)。
读入字符及每个字符的权值,建立哈夫曼树HuffTree;
2)编码(EnCoding)。
用已建好的哈夫曼树,对输入的文本进行编码形成报文,将报文显示出来;
3)译码(Decoding)。
利用已建好的哈夫曼树,对输入的代码进行解码形成原文,并将结果显示;
4)输出(Output):
输出出现的字符以及各字符出现的频度(或概率);输出各个字符的编码,输出代码译出的原文;
3.实验目的:
理解哈夫曼树的特征及其应用;在对哈夫曼树进行理解的基础上,构造哈夫曼树,并用构造的哈夫曼
树进行编码和译码;通过该实验,使学生对数据结构的应用有更深层次的理解。
4.实验条件:
学院提供公共机房,1台/学生微型计算机。
5.实验步骤(含实验代码)
第i次:
完成程序的主框架设计,进行调试,验证其正确性;
第2次:
详细设计,进行调试,验证其正确性;
第3次:
进行整体调试,运行程序,对运行结果进行分析,完成实验报告
#include
#include
#include
#defineMAXWORD100
typedefstruct
{unsignedintweight;chardata;
unsignedintparent,llchild,rrchild;
}HTNode,*HuffmanTree;
//动态分配数组存储哈夫曼树
typedefchar**HuffmanCode;
//动态分配数组存储哈夫曼编码
//字符
typedefstructtnode
{charch;
structtnode*lchild,*rchild;
}BTree,*BT;
inta=0,b=0;ints[MAXWORD];charstr[MAXWORD];
voidmain()
{intn;inti=0;
HuffmanTreeHT;HuffmanCodeHC;
voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,intn);
voidDispHCode(HuffmanTreeHT,HuffmanCodeHC,intn);
voidCreatree(BT&p,charc);//Creatree()和
InOrderTraverse()
voidInOrderTraverse(BTp);//利用二叉树统计出现的字符及个数voidTTranChar(HuffmanTreeHT,HuffmanCodeHC,intn);
voidTran(HuffmanTreeHT,intn);printf("请输入要用几种字符:
");scanf("%d",&n);
BTroot=NULL;
printf("\n");
printf("请输入字符串:
\n");scanf("%s",str);
while(str[i]!
='\0')
{Creatree(root,str[i]);i++;}
printf("字符及出现次数:
\n");
InOrderTraverse(root);
printf("\n");
HuffmanCoding(HT,HC,n);
DispHCode(HT,HC,n);
Tran(HT,n);
TTranChar(HT,HC,n);
voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,intn)
{//w放n个权值,构造赫夫曼树HT,n个字符编码HC
voidselect(HuffmanTreet,inti,int&s1,int&s2);
intm,i,s1,s2,start;char*cd;unsignedc,f;
HuffmanTreep;
if(n<=1)return;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(p=HT+1,i=1;i<=n;++i,++p)
{(*p).parent=0;
(*p).llchild=0;
(*p).rrchild=0;
}
for(p=HT+1,i=0;i{(*p).data=str[i];
(*p).weight=s[i];
for(;i<=m;++i,++p)
(*p).parent=0;
for(i=n+1;i<=m;++i)//建赫夫曼树
{//在HT[1~i-1]中选择parent为0且weights2
select(HT,i-1,s1,s2);
HT[s1].parent=HT[s2].parent=i;
HT[i].llchild=s1;
HT[i].rrchild=s2;
HT[i].weight=HT[s1].weight+HT[s2].weight;
}
HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//([0]
cd=(char*)malloc(n*sizeof(char));
cd[n-1]='\0';//
for(i=1;i<=n;i++)
最小的两个,分别s1、
不用)
编码结束符
{start=n-1;
//编码结束符位置
for(c=i,f=HT[i].parent;f!
=0;c=f,f=HT[f].parent)
if(HT[f].llchild==c)
cd[--start]='0';
else
cd[--start]='1';
HC[i]=(char*)malloc((n-start)*sizeof(char));
strcpy(HC[i],&cd[start]);//复制
}
free(cd);
}
voidselect(HuffmanTreet,inti,int&s1,int&s2)//s1为较小
{intmin(HuffmanTreet,inti);
intj;
s1=min(t,i);
s2=min(t,i);
if(s1>s2)
{j=s1;
s1=s2;
s2=j;
}
}
intmin(HuffmanTreet,inti)
{
intj,flag;
unsignedintk=100;
for(j=1;j<=i;j++)
if(t[j].weightt[flag].parent=1;
returnflag;
}
voidCreatree(BT&p,charc)
{if(p==NULL)
//函数voidselect()调用
//取k比任何权值都大
//采用递归方式构造一棵二叉排序树
//p为NULL,则建立一个新结点
{p=(BTree*)malloc(sizeof(BTree));
p->ch=c;
p->count=1;
p->lchild=p->rchild=NULL;
}
else
if(c==p->ch)p->count++;
else
if(cch)Creatree(p->lchild,c);
elseCreatree(p->rchild,c);
}
voidInOrderTraverse(BTp)//中序遍历
{
if(p!
=NULL)
{InOrderTraverse(p->lchild);
{printf("%c的个数为:
%d\n",p->ch,p->count);
s[b]=p->count;b++;
str[a]=p->ch;a++;}
InOrderTraverse(p->rchild);}
//显示0、
}
voidDispHCode(HuffmanTreeHT,HuffmanCodeHC,intn)
1编码
{inti;
printf("输出哈夫曼编码:
\n");
for(i=1;i<=n;i++)
{printf("%c:
\t",HT[i].data);
puts(HC[i]);}
}
1的编码翻译成字符
voidTran(HuffmanTreeHT,intn)//将含0、{
inti,j=0;
charcc[MAXWORD];
i=2*n-1;
printf("输入发送的(0、1)编码(以'#'为结束标志):
");
scanf("%s",cc);
printf("译码后的字符为");
while(cc[j]!
='#')
{
if(cc[j]=='0')
i=HT[i].llchild;
else
i=HT[i].rrchild;
if(HT[i].llchild==0)
{
printf("%c",HT[i].data);i=2*n-1;}
j++;
}
printf("\n");
}
voidTTranChar(HuffmanTreeHT,HuffmanCodeHC,intn)
charss[50];inti,j;
//将字符串翻译成0、1代码
printf("输入字符串:
");
scanf("%s",ss);
i=0;
while(ss[i]!
='\0')
{
j=1;
while((HT[j].data!
=ss[i])&&(j<=n))
{j++;}
printf("%s",HC[j]);
i++;
}
printf("\n");}
6.实验结果与总结:
時输入要用几种学符:
4
请输入宇符串:
aa^fTfjjjjjjjbbbbb
宇符及山现次数:
且的个数为:
2
b的个数为:
5
f的个散为
j的个数为:
了
输出哈夬昼編码:
a:
11O
七:
10
f:
111
J:
0
输入发:
送的(0、1)编码(UT护为结束标志);110101110010101111100^译码后的宁符为命fjjbbfaj输入宇符串'jj
00111111110100000011111100
P170S召匕门丫toGQntinuE
总结:
在实现哈夫曼树编码的过程中,首先构建哈夫曼树,并用动态分配数
组存储,也用动态分配数组存储哈夫曼编码表。
程序书上虽然有一部分可借鉴的代码,自己只需要编写几个函数即可,但在编写程序时也遇到一些问题,开始统计字符串中出现的各种字符及其次数时,将字母存放数组中,但是考虑到字母出现的不同,完全初始化再统计其出现的个数,不仅占用空间并且时间复杂度高。
后来采用二叉树统计出现的字母及个数,实现了输入字母种类的灵活性。
通过此次实验,明白了了解数据存储的具体方式的重要性,在这次实验中要实现两个互译码程序,就需要对数据的存储了解,编写时就容易了然于心。
总的来说,数据结构实验对我们的编程能力还是有很大的帮助,锻炼我们的逻辑思维、使我们更熟练地使用C语言编程、锻炼我们处理异常的能力