数据结构课程设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
井冈山大学
电子与信息工程学院数据结构课程设计报告
( 2012——2013年度第一学期)
课程名称:数据结构课程设计
题目一:6.3“哈夫曼树”的建立及其应用
题目二: 3.4.6括号匹配的检验
院系:计算机科学系
班级:10计本(一)班
姓名:刘晓倩
学号:100911012
指导教师:孙凌宇老师
成绩:
2012 年月日
成绩评定
一、指导教师评语
二、成绩
指导教师:
日期:年月日
设计题目<一>: 6.3“哈夫曼树”的建立及其应用
一、设计要求
1.问题描述
设有一段电文由字符集{A,B,C,D,E,F,G,H}组成,各字符在电文中出现的次数集为{5,29,7,8,14,23,3,11},试设计各字符的哈夫曼编码。
2.需求分析
(1)设计哈夫曼树。具体的构造方法如下:以字符集{A,B,C,D,E,F,G,H}作为叶子结点,以各字符出现的次数{5,29,7,8,14,23,3,11}作为各叶子结点的权值构造一棵哈夫曼树。
(2)设计哈夫曼编码。按照构造出来的哈夫曼树,规定哈夫曼树的左分支为0,右分支为1,则从根结点到每个叶子结点所经过的分支对应的0和1组成的序列便为该结点对应字符的哈夫曼编码。
二、概要设计
1.主界面设计
运行界面如图1所示:
图1哈夫曼编码主菜单
2.存储结构设计
对于哈夫曼编码问题,希望在构造哈夫曼树的同时能方便地实现从双亲结点到左右孩子结点的操作,在进行哈夫曼编码时又要求能方便地实现从孩子结点到双亲结点的操作。因此,本程序选择树的双亲孩子表示法作为哈夫曼树的存储结构,并加入了指示结点权值的信息。
3.系统功能设计
本程序完成了从哈夫曼树的构造到实现并输出哈夫曼编码的过程,分别由两个子程序完成,其设计如下:
(1)选择权值最小的树。选择权值最小的树由函数Select()实现。该功能按照哈夫曼树的构造步骤,在当前已构成的n(n>=2)棵二叉树的集合中选取两棵根结点权值最小的树作为左右子树构造一棵新的二叉树。
(2)哈夫曼编码。哈夫曼编码由函数HuffmanCoding( )实现。该功能首先调用函数Select()实现哈夫曼树的构造,然后从叶子到根逆向根据哈夫曼编码的要求,一次求出每个字符的哈夫曼编码。
三、模块设计
1.模块设计
本程序包含3个模块:主程序模块、哈夫曼编码模块和选择模块。其调用关系如图2所示。
图2 模块调用示意图
2.系统子程序及功能设计
本程序共设置3个子程序,各子程序的函数名及功能说明如下。
(1)void Select(HuffmanTree &HT,int m,int *s1,int *s2)
//选择权值最小的两个结点
(2)void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)
//构造哈夫曼编码
(3)void main( ) //主函数。输入结点个数及权值,调用哈夫曼编码模块函数3.函数主要调用关系图
本程序3个子程序之间的主要调用关系如图3所示。
图中数字是各函数的编号
图3系统函数调用关系图
四、详细设计
1.数据类型定义
typedef struct
{
unsigned int weight; //用来存放各个结点的权值
unsigned int parent, lchild, rchild; //指向双亲、孩子结点的指针}HTNode, *HuffmanTree; //动态分配数组存储哈夫曼树
typedef char * * HuffmanCode; //动态分配数组存储哈夫曼编码表
2.系统主要子程序详细设计
哈夫曼编码模块设计分两步:首先构造哈夫曼树,然后完成哈夫曼编码。
void HuffmanCoding(HuffmanTree &HT,HuffmanCode &HC,int *w,int n)
{//w存放n个字符的权值(均>0),构造哈夫曼树HT并求出n个字符的哈夫曼编码HC int i,j,m,s1,s2,start;
char *cd;
unsigned int c,f;
if (n<=1) return;
m = 2 * n - 1;
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); //0号单元未用
for (i=1;i<=n;i++) //叶子结点初始化并放入1-n号单元
{
HT[i].weight=w[i];
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=n+1; i<=m;i++) //非叶子结点初始化
{
HT[i].weight=0;
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
printf("\n哈夫曼树的构造过程如下所示:\n");
printf("HT初态:\n 结点weight parent lchild rchild");
for (i=1;i<=m;i++) //完成构造哈夫曼树算法的第1个步骤
printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight,HT[i].parent,HT[i].lchild, HT[i].rchild);
printf(" 按任意键,继续...");
getch();
//创建哈夫曼树HT
for (i=n+1;i<=m;i++)
{
Select (HT,i-1,&s1,&s2);
//在HT[1..i-1]中选择parent为0且weight最小的两个结点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;
//置新二叉树的根结点权值为其左、右子树根结点之和printf("\nselect:s1=%d s2=%d\n",s1,s2);
//根结点权值最小的树在HT中的位置
printf(" 结点weight parent lchild rchild");
for (j=1;j<=i;j++)
//输出选取根结点权值最小树的过程
printf("\n%4d%8d%8d%8d%8d",j,HT[j].weight,HT[j].parent,HT
[j].lchild,HT[j].rchild);
printf(" 按任意键,继续...");
getch();