数据结构课程设计-赫夫曼编码(C语言)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计报告
课程设计题目:赫夫曼编码系统
****:**
专业:计算机科学与技术
班级:1120702
学号:************
****:***
2012年06 月20 日
目录
一、设计要求------------------------------------2
二、存储结构------------------------------------2
三、设计思想------------------------------------2
1、设计包含的几个部分-----------------------2
2、流程图-----------------------------------3
四、详细设计------------------------------------4
五、算法复杂度分析------------------------------8
六、显示结果------------------------------------9
七、心得体会------------------------------------11
八、附录:源程序代码----------------------------11
一、设计要求
赫夫曼树
任务:建立建立最优二叉树函数
要求:可以建立函数输入二叉树,实现赫夫曼树的编码和译码系统,重复地显示并处理编码/解码功能,直到选择退出为止。
二、存储结构:
在本次课程设计中,每一个字符的信息用一个结构体存储,包含结点值、权值、双亲结点、左孩子结点、右孩子结点等数据。赫夫曼码和所有字符都是用一个一维数组建立存储的,所以本次课程设计的存储结构是顺序存储。
三、设计思想
哈夫曼编译码系统的主要功能是先建立哈夫曼树,然后利用建好的哈夫曼树生成哈夫曼编码后进行译码。
在通信中可以采用0和1的不同排列来表示不同的字符,称为二进制编码。而赫夫曼树在数据编码中的应用是数据的最小冗余编码问题他是数据压缩学的基础。若每个字符出现的频率相同,则可以采用等长的二进制编码,频率不同,采用不等长的二进制编码,频率达的字符采用位数较少的编码,频率小的采用位数较多的编码。赫夫曼编码就是一种不等长的二进制编码,而赫夫曼树是一种最优二叉树,它的编码也是一种最优编码。在赫夫曼树中,规定往左编码为0,往右编码为1,则得到叶子节点的编码为从根结点带叶子结点中所有路径中0和1的顺序排列。
(1)设计包含的几个方面:
①赫夫曼树的构造
假设有n个权值,则构造出的赫夫曼树有n个叶子结点。n个权值分别为w1,w2,………wn,则赫夫曼树构造规则为:
1、将w1,w2,…….wn,看成有n棵树的森林。
2、在森林中选出两个根结点最小的树合并,作为一棵新树的左右子书,
且新树根结点权值为左右子树根结点权值之和。
3、从森林中删除选取的两棵树,并将新树加入森林。
4、重复2和3步骤,直到森林中只剩一棵树为止。
②赫夫曼编码
要求电文的赫夫曼编码,必须先定义赫夫曼编码类型,根据设计要求和实际需要定义的类型如下:
typedet struct {
char ch; // 存放编码的字符
char bits[N+1]; // 存放编码位串
int len; // 编码的长度
}CodeNode; // 编码结构体类型
③代码文件的译码
在通信中,若将字符用赫夫曼编码形式发送出去,对方接收到编码后将编码还原成字符。译码的基本思想是:读文件中编码,并与原先生成的赫夫曼编码表
比较,遇到相等时,即取出其对应的字符存入一个新串中。(2)其主要流程图如图所示。
四、详细设计
(1)①赫夫曼树的存储结构描述为:
#define N 50 // 叶子结点数
#define M 2*N-1 // 赫夫曼树中结点总数
typedef struct {
int weight; // 叶子结点的权值
int lchild, rchild, parent; // 左右孩子及双亲指针
}HTNode; // 树中结点类型
typedef HTNode HuffmanTree[M+1];
②哈弗曼树的算法
void CreateHT(HTNode ht[],int n) //调用输入的数组ht[],和节点数n
{
int i,k,lnode,rnode;
int min1,min2;
for (i=0;i<2*n-1;i++)
ht[i].parent=ht[i].lchild=ht[i].rchild=-1; //所有结点的相关域置初值-1 for (i=n;i<2*n-1;i++) //构造哈夫曼树
{
min1=min2=32767; //int的范围是-32768—32767
lnode=rnode=-1; //lnode和rnode记录最小权值的两个结点位置
for (k=0;k<=i-1;k++)
{
if (ht[k].parent==-1) //只在尚未构造二叉树的结点中查找
{
if (ht[k].weight { min2=min1;rnode=lnode; min1=ht[k].weight;lnode=k; } else if (ht[k].weight { min2=ht[k].weight;rnode=k; } } } ht[lnode].parent=i;ht[rnode].parent=i; //两个最小节点的父节点是i ht[i].weight=ht[lnode].weight+ht[rnode].weight; //两个最小节点的父节点权值为两个最小节点权值之和 ht[i].lchild=lnode;ht[i].rchild=rnode; //父节点的左节点和右节点} }