数据结构课程设计实验报告赫夫曼编码.docx
- 文档编号:8179886
- 上传时间:2023-01-29
- 格式:DOCX
- 页数:29
- 大小:87.20KB
数据结构课程设计实验报告赫夫曼编码.docx
《数据结构课程设计实验报告赫夫曼编码.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计实验报告赫夫曼编码.docx(29页珍藏版)》请在冰豆网上搜索。
数据结构课程设计实验报告赫夫曼编码
+
南京信息工程大学
数据结构课程设计
题目:
赫夫曼编码
院、系:
滨江学院
学科专业:
计算机科学与技术
学生:
学号:
指导教师:
王鹤蒙
2010年12月22日
目录
1课程设计的题目-----------------------------0
2课程设计的目的(设计要解决的问题)----------1
3概要设计(函数划分、总体设计)----------------1
4详细设计(算法、流程图、程序)-----------------2
5调试结果---------------------------------32
6课程设计总结-----------------------------33
7心得体会----------------------------------34
二课程设计的目的
<1>巩固构造赫夫曼树的算法。
<2>设计实验用程序实现赫夫曼树的构造。
<3>熟悉用先序、中序或后序的访问方法得到个叶子结点的赫夫曼编码。
三概要设计(函数划分、总体设计)
<一>总体设计
(1)输入一个字符串用结构体链表存储字符串中出现的不同字符及其出现的次数。
(2)定义赫夫曼数的结点结构体,把不同的字符及其在字符串中出现的次数作为叶子结点的元素及其权值,统计叶子结点的个数n,开辟可以存储2*n个结点的顺序表,来赫夫曼树的各个结点,然后按照一定的规则构造赫夫曼树。
(3)开辟一个可以存储叶子结点元素及指向存储其赫夫曼编码链表的指针的顺序表,然后从叶子结点开始向上访问,是左孩子的把“0”接进链表是右孩子的把“1”接进链表,直到根结点,然后把叶子结点的元素及存储其赫夫曼链表的头指针读入顺序表,直到把所有的叶子结点的元素及指向存储其赫夫曼编码链表的头指针读入顺序表,这样得到的赫夫曼编码是倒序的。
(4)从存储其叶子结点及指向存储其赫夫曼编码链表头指针的顺序表表头开始顺序访问各元素,在输出其赫夫曼编码之前,把链表中的编码顺序读入到等长的栈中,然后编码出栈就会得到顺序的赫夫曼编码,直到把所有的叶子结点都访问到。
(5)用一个字符型的指针指向字符串的第一个字符,从存储叶子结点元素及指向存储其赫夫曼编码链表的头指针的顺序表表头开始访问顺序表中的各元素,直到找到叶子结点的元素和当前字符相等就结束访输出赫夫曼编码,回到表头,指针后移,直到输出字符串的最后一个字符的赫夫曼编码,这样就得到输入字符串的赫夫曼编码。
<二>函数划分
该程序有一个主函数和多个子函数,主函数完成对子函数的调用,各子函数实现相应的功能。
子函数:
(1)结点的开辟。
(2)实现对输入字符串中出现的不同字符及其出现字数的信息记录。
(3)用叶子结点构造赫夫曼树。
(4)获得构造的赫夫曼树中所有叶子结点的元素及其赫夫曼编码。
(5)输出各叶子结点元素及其对应的赫夫曼编码。
(6)输出输入的字符串的赫夫曼编码。
(7)调用各子函数
四详细设计(算法、流程图、程序)
<一>算法
<1>创建存储叶子结点元素及其权值的链表
定义结构体node,其数据成员包括,字符型的元素a和整型元素b和指向node的next指针,来存储叶子结点的内容和权值。
定义三个指向node的指针head、p1、p2和字符指针n、t、h,调用setnode()函数开辟一个结点让head指向该结点,p1=head,让n指向输入字符串的第一个元素,当n指向的内容不是‘\0’时,如果n指向字符串的第一个字符,则开辟一个结点,让p2指向该结点,让t指向字符串的第一个元素,当*t!
=‘\0’并且*t==*n则r++(r为整型,初始值为0),把p2->a=*n,p2->b=r,p1->next=p2,p1=p2,n++,t回到字符串首;否则i++(i为整型,初始值为1)r=0,j=1;让t指向字符串第一个元素,当*t!
=‘\0’,如果*t==*n,r++,t++;让h指向字符串的第一个元素,当h!
=n时如果*h==*n就跳出此循环,否则,j++,h++如果i==j则开辟新的结点p2->a=*n,p2->b=r,p1->next=p2,p1=p2
;n++,当把最后一个结点连入链表中,p1->next=NULL,然后把p1=head->next,当p!
=NULL时输出结点中叶子结点的元素和对应的权值;最后返回head。
//setnode()函数的算法:
设指向node的指针p,用malloc开辟一个node结点并让p指向该结点,返回p。
<2>构造赫夫曼树
定义结构体node1,其数据项字符型a(存放叶子结点元素)、整型weight(存放对应权值)、整型sign(起标记作用)、和指向左、右孩子及父母结点的指针lchild、rchild和parent。
定义指向node1的指针p0、p1、p2、p3、p4和整型的m、n、i、j、k1、k2,n=0、p=head->next,当p!
=NULL,n++,p=p->next,开辟可以存储2*n个node1的顺序表,让p0指向表头,p1=p0,p=head->next,当p!
=NULL时p1->a=p->a,p1->weight=p->b
p1的指向左、右孩子及父母的指针指空,p=p->next,p1++;p1++,p=p->next;i=1,当i<=n-1,j=0,当j<2,如果j==0把‘‘1’赋给k1;否则把‘1’赋给k2;p2=p0,当p2!
=p1时,如果p2->sign==NULL并且m=p2->weight用break结束循环否则p2++;p2=p0,当p2!
=p时,如果m>=p2->weight并且p2->sign==NULL,把p2->weight赋给m,否则p2++;把p0赋给p2,当p2不等于p1时,如果m等于p2->weight并且p2->sign等于NULL,把‘1’赋给p2->sign,如果j=0,把p2赋给p1->lchild,p2->weight赋给p1->weight,p1赋给p2->parent,用break结束循环;如果j==1,则把p2赋给p1->rchild,p1->weight加p2->weight赋给p1->weight,p1赋给p2->parent,用break结束循环;如果j等于0,k1++,p2++;如果j等于1,k2++,p2++;j++;如果k1大于k2把p1->lchild赋给p3,p1->rchild赋给p4,p4赋给p1->lchild,p3赋给p1->rchild,p1->sign=
NULL,p1++,i++;然后p--,把p1->parent=NULL,p1++,把p0赋给p2,当p2不等于p时输出p2的各数据项,拍p2++;返回p0。
<3>获得各叶子结点的赫夫曼编码
定义只存储赫夫曼编码的结构体code,它的数据项有字符型的a(存储‘0’、‘1’编码)以及指向下一个结点的指针next。
定义结构体huffmancode,它的数据项有字符型a(存储叶子结点元素)、指向结构体code的指针head。
设指向node1的指针p1、p2、p4,指向huffmancode的指针l、l1和指向code的指针h、h1,把p(p为函数的形参)赋给p2,当p2->lchild和p2->rchild同时为NULL,n++,(n为整型,初始化为零),p2++;调用malloc函数开辟可以存储n+1个huffmancode结点的顺序表,让l指向该顺序表的表头,把l赋给l1,把p赋给p4,当p4->lchild和p4->rchild同时为NULL把p4赋给p1调用setcode()函数开辟一个结点让h1指向该结点,把h1赋给l1->head,当p1->parent不等以NULL时,如果p1等于p1->parent->lchild,调用setcode()函数让h指向它,h->a=‘0’,h1->next=h,h1=h;否则,调用setcode()函数开辟一个结点让h指向它,h->a=‘1’,h1->next=h,h1=h;然后,把p1->parent赋给p1,把NULL赋给h1->next,p4->a赋给l1->a,l++,当把所有的叶子结点元素及其赫夫曼编码读入顺序表后把NULL赋给l1->a;返回l。
//setcode()函数的算法:
设指向code的指针p,调用malloc()函数开辟一个code结点,让p指向该结点,返回p。
<4>输出各叶子结点的赫夫曼编码
设指向huffmancode的指针p,指向code的指针和指向字符型的指针base、top;把head1(函数的形参)赋给p,当p->a!
=NULL时,把0赋给n,p->head->next赋给h,当h!
=NULL时n++,h=h->next,开辟一个可以存储n+1个字符的栈,让base指向栈底,top=base,把h=p->head->next,当h!
=NULL时,*top=h->a,top++,h=h->next;top--,当to不等于base时,输出*top,top--;输出*top;p++。
<5>输出字符串的赫夫曼编码
设指向huffmancode的指针p1,指向code的指针h和指向字符型的指针base,top,p2,让p2指向字符串的第一个元素,当*p2!
=‘\0’时,输出*p2,p2++;当*p!
=‘\0’时(p为函数的形参),把0赋给n(n为整型)p1=p0(p0为形参)当p1->a!
=NULL时,如果p1->a等于*p把p1->head->next赋给h,当h!
=NULL时,h=h->next,base指向可以存储n+1个字符的栈底,top=base,把p1->head->next赋给h,当h!
=NULL,*top=h->a,top++,h=h->next,top自减,当top!
=base,输出*top,top--,输出*top,用break结束循环,p++。
<6>control函数
定义长度为20的字符数组a,指向node的指针p,整型n和指向node1的指针p1,输入a把a作为实参调用函数getdata(a),把返回值赋给p,把p作为实参调用coutdata(p)把返回值赋给n,如果n等于1,p=p->next,输出p->a和p->b,否则,以p为实参调用settree(p),将返回值赋给p1,以p1为实参调用gethuffmamcode(p1)函数,将返回值赋给p2(p2为指向huffmancode的指针),以p2为实参调用printhuffmancode(p1)函数,然后以a,p2为实参调用print(a,p2)函数。
//coutdata()函数的算法:
设指向node的指针p,把head->next赋给p,当p!
=NULL时n++,p=p->next;返回n。
<7>主函数
调用control()函数。
<二>流程图
创建存储叶子结点元素及其权值的链表
开辟一个新的结点,让head指向它
p1=head
n=a
*n!
=‘\0’
n=
是
=a?
否
开辟新的结点,让p1指向它
i++
r=0
t=n
j=1
*t!
=‘\0’
t=a
*t=
是
=‘\0’?
否
*t!
=‘\0’
*t==*n
是
?
否
r++
r++
t++
t++
p2->a=*n
h=a
p2->b=r
h!
=n
p1->next=p2
*h==
是
*n?
否
p1=p2
n++
break
j++
h++
i==j?
是
否
开辟新结点,让p2指向它
p2->a=*n
p2->b=r
p1->next=p2
p1=p2
p1->next=NULL
p1=head->next
p1!
=NULL
输出p1->a
输出p1->a
返回head
//setnode函数
开辟一个node结点,让p指向它
返回p
构造赫夫曼树
p=head->next
p!
=NULL
n++
p=p->next
p0=(listnode1)malloc(2*n*sizeof(node1))
p1=p0
p=head->next
p!
=NULL
p1->a=p->a
p1->weight=p->b
p1->lchildp1->rchildp1->parentp1->sign全置空
p1++
i=1
i<=n-1
j=0
j<2
是
j==0?
否
k1=1
k2=1
p2=p0
p2!
=p1
是
P2->sign==NULL?
否
m=p2->weight
p2++
break
p2=p0
p2!
=p1
m>=p2->weight
是
并且p2->sign==NULL?
否
m=p2->weight
p2++
p2=p0
p2!
=p1
m==p2->weight
是
并且p2->sign==NULL?
否
j==0?
是
p2->signj==0?
==1?
是
否
p1->lchild=p2p1->rchild=p2
p1->weightp1->weight+=k1++
=p2->weightp2-weight
k2++
p2->parentp2->parent
=p1
=p1
break
p2++
j++
k1>k2
是
?
否
p3=p1->lchild
p4=p1->rchild
p1->lchild=p4
p1->rchild=p3
p1->sign=NULL
p1++
i++
p1--
p1->parent=NULL
p1++
p2=p0
p2!
=p1
输出p2->ap2->weight
p2->lchildp2->parentp2->rchild
p2++
返回p0
<3>获得各叶子结点的赫夫曼编码
p2=p
p2=lchild==NULL&&p2->rchild==NULL
n++
p2++
l=(listhuffmancode)malloc((n+1)*sizeof(huffmancode))
p4=p
p4->lchild==NULL&&p4->rchild==NULL
p1=p4
h1=setcode()
l1->head=h1
P1->parent!
=NULL
是
p1=p1->parent->lchild?
否
开辟一个结点让h指向它
h->a=‘\0’
h1->next=h
h1=h
h->a=‘\0’
h1->next=h
h1=h
h1->next=NULL
l1->a=p4->a
l1++
l1->a=NULL
返回l
//setcode函数
开辟一个code结点,让p指向该结点
返回p
<4>输出各叶子结点的赫夫曼编码
p=head1
p->a!
=NULL
h=h->head->next
h!
=NULL
n++
h=h->next
base=(char*)malloc((n+1)*sizeof(char))
h=h->head->next
h!
=NULL
*top=h->a
top++
h=h->next
top--
top!
=base
输出*top
top--
输出*top
<5>输出字符串的赫夫曼编码
p2=p
*p2!
=‘\0’
*p2
p2++
*p!
=‘\0’
n=0
p1=p0
p1->a!
=NULL
p1->a==*p?
是
否
h=p1->head->next
p1++
h!
=NULL
n++
h=h->next
base=(char*)malloc((n+1)*sizeof(char))
top=base
h=p1->head->next
h!
=NULL
*top=h->a
top++
h=h->next
--top
top!
=base
输出*top
break
p++
<6>control函数
输入a
p=getdata(a)
n=coutdata(p)
是
n==1?
否
p=p->next
p1=settree(p)
输出p->a和p->b
p2=gethuffmancode(p1)
printhuffmancode(p2)
print(a,p2)
//countdata()函数
p=head-next
p!
=NULL
n++
p=p->next
返回n
<7>主函数
调用control()函数
//程序的编译环境是Visualstudio2010
//把统计叶子结点元素和权值的函数放在“计算权值.h”中
#include
usingnamespacestd;
typedefstructnode//存储叶子结点元素及其权值的结构体
{
chara;//叶子结点的元素
intb;//叶子结点的权值
structnode*next;//指向下一个结点的指针
}*listnode;
listnodesetnode()//开辟结点的函数
{
listnodep;
p=(listnode)malloc(sizeof(node));
returnp;
}
listnodegetdata(char*a)/*统计输入字符串中的不同字符及其出现的次数的函并且把统计出的数据,作为叶子结点的元素和权值*/
{
listnodehead,p1,p2;
char*n,*t,*h;
inti=1,j=1,r=0;
head=setnode();
p1=head;
for(n=a;*n!
='\0';n++)
{
if(n==a)
{
p2=setnode();
for(t=n;*t!
='\0';t++)//统计相同的字符在字符串中出现的次数
if(*t==*n)
r++;
p2->a=*n;
p2->b=r;
p1->next=p2;
p1=p2;
}
else
{
i++;
r=0;
j=1;
for(t=a;*t!
='\0';t++)
if(*t==*n)
r++;
for(h=a;h!
=n;h++)
{
if(*h==*n)
break;
else
j++;
}
if(i==j)
{
p2=setnode();//调用setnode()函数开辟结点
p2->a=*n;
p2->b=r;
p1->next=p2;
p1=p2;
}
}
}
p1->next=NULL;
cout<<"电文的长度为:
"<
cout<<"------------------------------------------------"< p1=head; cout<<"叶子结点"<<"\t"<<"权值"< for(p1=p1->next;p1! =NULL;p1=p1->next) cout< cout<<"------------------------------------------------"< returnhead; } intcoutdata(listnodehead)//统计叶子结点的个数 { listnodep; intn=0; for(p=head->next;p! =NULL;p=p->next) n++; returnn; } //把构造赫夫曼树的函数放在头文件“构造赫夫曼树.h”中 #include #include"计算权值.h" usingnamespacestd; typedefstructnode1//赫夫曼树的结点结构体 { chara;//结点元素 intweight,sign;//结点的权值和结点的标记 structnode1*parent,*lchild,*rchild;//指向父母结点和左、右孩子的指针 }*listnode1;//指向node1的指针 listnode1settree(listnodehead)//构造赫夫曼树的函数 { listnodep; listnode1p0,p1,p2; intm,n,i,j,k1,k2; structnode1*p3,*p4; n=0; for(p=head->next;p! =NULL;p=p->next) n++; p0=(listnode1)malloc(2*n*sizeof(node1));//开辟可以存储2n个赫夫曼树结点的顺序表 p1=p0; for(p=head->next;p! =NULL;p=p->next)//把叶子结点的信息读入到顺序表中 { p1->a=p->a; p1->weight=p->b; p1->lchild=NULL; p1->parent=NULL; p1->rchild=NULL; p1->sign=NULL; p1++; } for(i=1;i<=n-1;i++) { for(j=0;j<2;j++) { if(j==0) k1=1; elseif(j==1)k2=1; for(p2=p0;p2! =p1;p2++) if(p2->sign==NULL) { m=p2->weight; break; } for(p2=p0;p2! =p1;p2++) if(m>=p2->weight) if(p2->sign==NULL) m=p2->weight; for(p2=p0;p2! =p1;p2++) { if(m==p2->weight) if(p2->sign==NULL) { p2->sign=1; if(j==0)//把先找到的权值最小的作为左孩子 { p1->lchild=p2;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 实验 报告 赫夫曼 编码