课程设计文档格式.docx
- 文档编号:19048895
- 上传时间:2023-01-03
- 格式:DOCX
- 页数:9
- 大小:74.84KB
课程设计文档格式.docx
《课程设计文档格式.docx》由会员分享,可在线阅读,更多相关《课程设计文档格式.docx(9页珍藏版)》请在冰豆网上搜索。
4.2算法描述………………………………………………………………1
4.3调试过程………………………………………………………………7
4.4具体结果………………………………………………………………7
4.5结果讨论………………………………………………………………8
5总结………………………………………………………………………8
参考文献……………………………………………………………………8
1.设计目的
(1).掌握二叉树的二叉链表存贮结构。
(2).掌握优先队列的基本运算实现。
(3).掌握Huffman树的算法实现。
2.设计要求
完成二叉树的设计实现,利用二叉树的基本操作和优先队列去构造Huffman树,并生成Huffman编码。
3.设计方案
①将n个权值分别为w
w
……,w
的结点按权值递增排序。
将每个权值作为一棵二叉树,构成n棵二叉树的森林F={T
T
……,T
},其中每棵二叉树T
都只有一个权值为w
的根结点,其左、右子树均为空。
②在森林F中选取两棵根结点权值最小的二叉树,作为左、右子树构造一棵新的二叉树,并使得新二叉树根结点的权值为其左、右子树上根结点的权值之和。
③在森林F中,删除这两棵树,同时将新得到的二叉树代替这两棵树加入森林F中。
因此,森林F中二叉树的个数将比以前少一棵。
④对新的森林F重复②和③,直到森林F中只有一棵树为止。
这棵树就是哈夫曼树。
⑤利用哈夫曼树进行编码,求出每个叶子结点所代表字母的编码。
并且还可完成译码。
4.设计内容
4.1实验步骤
(1)根据算法思想,构造哈夫曼树,由哈夫曼树对给定的字符进行哈夫曼编码和译码。
输入程序,然后编译、运行,发现错误进行调试。
(2)调试完成后无误,再次编译、运行,观察并记录输出结果。
(3)通过运行结果与自己完成的结果作比较,确认无误即实验成功。
4.2算法描述
#include“stdio.h”/*建立哈夫曼树,完成给定字符的哈夫曼编码和译码程序*/
#include“conio.h”/*文件包含清屏*/
#defineleafnum7/*哈夫曼树中叶结点个数*/
#definehufnum2*leafnum/*哈夫曼树结点总数*/
#definemaxfloat999.9/*maxfloat为float类型最大值999.9*/
typedefstructtnode/*结点的类型*/
{charname;
/*结点的字符名称*/
floatweight;
/*结点的带权值*/
intlchild,rchild,parent;
/*结点左、右孩子及双亲指针*/
}huftree;
/*哈夫曼树的类型定义*/
typedefstructcnode/*结点的类型*/
{charbits[leafnum+1];
/*存储哈夫曼编码位串*/
intstart;
/*哈夫曼编码在位串中的起始位置*/
charch;
/*编码字符的名称*/
intlchild,rchild,parent;
}hufcode;
/*哈夫曼编码的类型定义*/
hufcodecode[leafnum+1];
/*哈夫曼编码表*/
huftreetree[hufnum+1];
/*用静态的带双亲孩子链表数组存储哈夫曼树*/
charch[8]={‘\0’,’a’,’b’,’c’,’d’,’e’,’f’,’g’};
/*存储字符名称*/
floatw[8]={0,7,5,1,4,8,10,20};
/*字符出现的频率*/
voidcreattreehuffman(huftreetree[])/*根据叶结点权值建立哈夫曼树*/
{inti,j,p1,p2;
/*定义整型变量i,j,p1,p2*/
floatleast1,least2;
/*定义字符型变量least1,least2*/
for(i=1;
i<
=hufnum+1;
i++)/*将哈夫曼树初始化*/
{tree[i].name=‘\0’;
/*名称为0*/
tree[i].parent=0;
/*双亲为0*/
tree[i].lchild=0;
/*左孩子为0*/
tree[i].rchild=0;
/*右孩子为0*/
tree[i].weight=0.0;
/*权值为0*/
}
for(i=1;
=leafnum;
i++);
/*输入待编码的字符及带权值*/
{tree[i].name=ch[i];
/*输入叶结点所代表的字符*/
tree[i].weight=w[i];
/*输入叶结点的带权值*/
}
for(i=leafnum+1;
i++)/*进行合并,新结点存储于tree中*/
{p1=0;
p2=0;
/*令p1,p2为0*/
least1=maxfloat;
/*为least1赋初值*/
least2=maxfloat;
/*为least2赋初值*/
for(j=1;
j<
i;
j++)/*选出两个权最小的根节点*/
if(tree[j].parent==0)/*权值最小结点的序号为p1和p2*/
if(tree[j].weight<
least1)/*如果权值小于least1则执行*/
{least2=least1;
/*改变最小权值和次小权值及其对应位置*/
least1=tree[j].weight;
p2=p1;
p1=j;
else
least2)/*如果权值小于least2则执行*/
{least2=tree[j].weight;
/*改变次小权值及其位置*/
p2=j;
tree[p1].parent=i;
/*设置新结点的双亲指针*/
tree[p2].parent=i;
tree[i].lchild=p1;
/*最小根结点是新结点的左孩子*/
tree[i].rchild=p2;
/*次小根结点是新结点的右孩子*/
tree[i].weight=tree[p1].weight+tree[p2].weight;
/*新结点权值是两孩子权值之和*/
}/*FOR*/
tree[hufnum-1].parent=0;
/*将根结点的双亲结点位置为0*/
}/*CREATTREEHUFFMAN*/
voidcreatcodehuffman(code,tree)/*根据哈夫曼树求出所给字符集的哈夫曼编码*/
hufcodecode[];
/*存储字符的哈夫曼编码表*/
hufcodetree[];
/*存储已建哈夫曼树的所有结点*/
{inti,c,p;
/*定义整型变量i,c,p*/
hufcodebuf;
/*buf为临时变量,用于存储编码位串*/
i++)/*从叶结点出发向上回溯*/
{buf.ch=ch[i];
buf.start=leafnum;
c=i;
p=tree[i].parent;
/*p为树的双亲结点*/
while(p!
=0)/*当p不为0时则循环*/
{buf.start--;
/*buf。
start自减*/
if(tree[p].lchild==c)/*如果p的左孩子为c则执行*/
buf.bits[buf.start]=‘0’;
/*若为树的左分支,则生成代码0*/
elsebuf.bits[buf.start]=‘1’;
/*若为树的右分支,则生成代码1*/
c=p;
p=tree[p].parent;
}/*WHILE*/
code[i]=buf;
/*将第i个字符编码存到编码表code[i]中*/
}/*CREATCODEHAFFMAN*/
voidprinttreehuffman(tree)/*输出根据字符使用概率构造的哈夫曼树*/
huftreetree[];
{inti;
/*定义整型变量i*/
printf(“\n\t根据字符的使用频率所建立的哈夫曼树为:
\n”);
printf(“\n\t字符序号字符名称使用频率双亲位置左孩子右孩子\n”);
hufnum;
{printf(“\tNO%d\t%6c”,i,tree[i].name);
/*输出字符名称*/
printf(“%6.2fp=%2d”,tree[i].weight,tree[i].parent);
/*输出权值和双亲*/
printf(“%8d%8d\n”,tree[i].lchild,tree[i].rchild);
/*输出左孩子和右孩子*/
}getchar();
/*输入字符*/
}/*PRINTTREEHUFMAN*/
voidprintcodehuffman(code)/*输出每个字符的哈夫曼编码*/
{inti,j;
/*定义整型变量i,j*/
printf(“\n\n\t根据哈夫曼树对字符所建立的哈夫曼编码为:
\n\n”);
printf(“\t字符序号字符名称字符编码字符串起始位置\n”);
{printf(“\tNO%d\t\t%c\t”,i,code[i].ch);
for(j=code[i].start;
leafnum;
j++)
printf(“%c”,code[i].bits[j]);
/*输出字符位串*/
printf(“\t\t%d\n”,code[i].start);
/*输出位串起始位置*/
}/*PRINTCODEHUFFMAN*/
voidtranscodehuffman(code,tree)/*将输出哈夫曼编码串翻译成对应的字符函数*/
/*已经构成的哈夫曼树*/
/*已知的哈夫曼编码位串表*/
char*q;
/*定义指针变量q*/
chars[leafnum+1]={‘\0’};
/*初始化*/
q=NULL;
/*将q指针所指数据初始为空*/
printf(“\n\t请输入二进制编码(以’9’结束)”);
scanf(“%s”,s);
/*输入一个二进制编码串*/
while(s[0]!
=‘9’)/*若输入结束符9,则停止输入*/
{i=hufnum-1;
/*从根结点开始往下搜索*/
q=s;
while(*q!
=‘\0’)/*若q所指指针不为停止符则循环*/
{if(*q==‘0’)i=tree[i].lchild;
/*若编码是0,则进入左孩子*/
if(*q==‘1’)i=tree[i].rchild;
/*若编码是1,则进入右孩子*/
if((tree[i].lchild==0)&
&
(tree[i].rchild==0))/*若是叶结点,则进行译码*/
{printf(“\n\t若哈夫曼编码的二进制串为:
%s”,s);
printf(“\n\t则哈夫曼编码代表的字符为:
%c\n”,code[i].ch);
elseq++;
/*继续向下进行搜索*/
}/*WHILE2*/
printf(“\n\t请继续输入二进制编码(以’9’结束):
”);
/*输入二进制编码串进行译码*/
}/*WHILE1*/
}/*TRANSCODEHUFFMAN*/
main()/*构造哈夫曼树并进行哈夫曼编码和译码程序*/
{clrscr();
/*函数功能为清屏*/
creattreehuffman(tree);
/*根据字符的使用概率构造哈夫曼函数*/
printtreehuffman(tree);
/*输出哈夫曼树函数*/
creatcodehuffman(code,tree);
/*根据哈夫曼树求哈夫曼编码函数*/
printcodehuffman(code);
/*输出哈夫曼编码函数*/
transcodehuffman(code,tree);
/*将输入的二进制编码翻译成对应的字符函数*/
}/*MAINHUFFMAN*/
4.3调试过程
(1)发现错误提示“Possibleuseof‘q’beforedefinitioninfunctiontranscodehuffman”,只要将“*q”前的“*”去掉即可。
(2)发现警告提示“‘parent’notpartofstructureinfunctioncreatcodehuffman.”和“‘lchild’notpartofstructureinfunctioncreatcodehuffman.”,需要在结构体ncode中加入定义结点左、右孩子及双亲指针,即加入“intlchild,rchild,parent;
”。
4.4具体结果
4.5结果讨论
设计的程序得到的结果是符合算法的目的的。
建立的哈夫曼树能正常使用,编码可以正常变换为译码。
所得结果与预期的结论相同。
5.总结
通过这次哈夫曼树相关内容的课程设计,我掌握了构造哈夫曼树的算法,进一步加深对带权路径在哈夫曼树中的应用,与平时练习的习题结合考查哈夫曼树的优点。
并且还掌握了哈夫曼树的应用即编码和译码的编程。
可利用本次课程设计知识在电报通信中大展身手。
此外,利用之前学过的二叉树的二叉链表存贮结构以及优先队列的基本运算实现的知识的融会贯通构造哈夫曼树,体现了《算法与数据结构》这门课程所内涵的知识拓展性。
总之,这次的课程设计实验让我受益匪浅。
参考文献
[1]宁正元,王秀丽.《算法与数据结构》.北京:
清华大学出版社,2006.1.
[2]宁正元,王秀丽,林大辉.《算法与数据结构习题精解和实验指导》.北京:
清华大学出版社,2007.5.
[3]田鲁民.《数据结构》.北京:
电子工业出版社,2006.8.
[4]严蔚敏、吴伟民.《数据结构》.北京:
清华大学出版社,1997.4.
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 课程设计