数据结构研究论文.docx
《数据结构研究论文.docx》由会员分享,可在线阅读,更多相关《数据结构研究论文.docx(16页珍藏版)》请在冰豆网上搜索。
![数据结构研究论文.docx](https://file1.bdocx.com/fileroot1/2023-2/2/cae54221-7ec9-4209-96bb-b9f808a15250/cae54221-7ec9-4209-96bb-b9f808a152501.gif)
数据结构研究论文
计算机数据结构研究论文
题目:
院系:
计算机科学与信息工程系
专业:
网络工程
班级:
(1)班
姓名:
侯三杰
学号:
日期:
Huffman编码器与Joseph约瑟夫环
<一>.Huffman编码器
1.问题描述:
给出一个霍夫曼树的节点,和每个节点的权值,设计一个算法,可以通过算法将每个节点译为不同的码字.
2.需求分析
(1)输入的形式和输入值的范围;
输入的值是通过用户界面提示,输入名节点数和权值,但是要求均是正整数.
(2)输出的形式:
以表的形式输出,左边为要译的权值,右边为要译的码字,且是二进制码,
(3)程序所能达到的功能;将已知有权值的数译成二进制编码,且码不重复,无前缀码。
(4)测试数据:
number:
6,weight:
223456
输出:
1-0002-0013-1104-1115-016-10
3.概要设计
1.抽象数据类型的定义为:
voidCreateHuffmanTree(HuffmanTree*HT,unsignedint*w,intn)
输出结果:
w存放n个字符的权值(均>0),构造Huffman树HT.
voidSelect(HuffmanTreeHT,intt,int*s1,int*s2)
输出结果:
在Huffman树HT中找出权值最小的两个节点,序号分别为s1和s2
voidHuffmanCoding(HuffmanTreeHT,HuffmanCode*HC,intn)
输出结果:
赫夫曼编码,放入HC中
voidPrintHuffmanCode(HuffmanCodeHC,unsignedint*w,intn)
输出结果:
w存放n个字符的权值(均>0),输出Huffman编码
2.本程序包含以下模块:
(1)主程序模块:
main(void)
{
输入数据;
执行功能;
显示结果;
}
(2)各功能模块——实现Huffman编码的各项功能。
各模块的调用关系:
4.详细设计:
/*编辑器devcpp*/
#include
#include
#include
typedefstruct
{
unsignedintweight;/*放权值*/
unsignedintparent;/*父亲结点*/
unsignedintlchild;/*左孩子*/
unsignedintrchild;/*右孩子*/
}HTNode,*HuffmanTree;/*动态申请赫夫曼树*/
typedefchar**HuffmanCode;/*动态分配赫夫曼表*/
voidCreateHuffmanTree(HuffmanTree*HT,unsignedint*w,intn);
voidSelect(HuffmanTreeHT,intt,int*s1,int*s2);
voidHuffmanCoding(HuffmanTreeHT,HuffmanCode*HC,intn);
voidPrintHuffmanCode(HuffmanCodeHC,unsignedint*w,intn);
main(void)
{
HuffmanTreeHT;
HuffmanCodeHC;
inti,n;
unsignedint*w;
printf("*********Huffman********\n\n");
printf("inputnumberofHuffman:
\n");
scanf("%d",&n);
if(n<=1)return0;
w=(unsignedint*)malloc(n*sizeof(unsignedint));
printf("inputweight:
\n");/*输入每个叶子节点的权值*/
for(i=0;i{
scanf("%d",&w[i]);
}
CreateHuffmanTree(&HT,w,n);
HuffmanCoding(HT,&HC,n);
PrintHuffmanCode(HC,w,n);
getch();
}
/*****************************
建立赫夫曼树,w存放权值,在每次把两个小的权值相加后,在每次select中都能包括进去新的结点每次父亲结点被重新赋值,不为0在每次select中除去
*****************************/
voidCreateHuffmanTree(HuffmanTree*HT,unsignedint*w,intn)
{
inti,m;
ints1,s2;
char*cd;
m=2*n-1;/*总结点数*
*HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(i=1;i<=n;++i,++w)/*叶子结点初试化*/
{
(*HT)[i].weight=*w;
(*HT)[i].parent=0;
(*HT)[i].lchild=0;
(*HT)[i].rchild=0;
}
for(;i<=m;++i)
{
(*HT)[i].weight=0;
(*HT)[i].parent=0;
(*HT)[i].lchild=0;
(*HT)[i].rchild=0;
}
for(i=n+1;i<=m;++i)
{
Select(*HT,i-1,&s1,&s2);/*从权值中选两个最小的*/
(*HT)[s1].parent=i;/*父亲结点都被赋值,在select循环中可以除去*/
(*HT)[s2].parent=i;
(*HT)[i].lchild=s1;/*孩子结点被赋值*/
(*HT)[i].rchild=s2;
(*HT)[i].weight=(*HT)[s1].weight+(*HT)[s2].weight;/*加后成新结点*/
}
}
/*寻找两个最小的结点s1,s2*/
voidSelect(HuffmanTreeHT,intt,int*m1,int*m2)
{inti,max;
ints1,s2;
for(i=1;i<=t;i++)
if(HT[i].parent==0){
if(max<=HT[i].weight)
max=HT[i].weight;
}
s1=s2=max;
for(i=1;i<=t;i++)
if(HT[i].parent==0)
if(HT[i].weight{s2=s1;
*m2=*m1;
s1=HT[i].weight;
*m1=i;
}
elseif(HT[i].weight{s2=HT[i].weight;
*m2=i;
}
}
voidHuffmanCoding(HuffmanTreeHT,HuffmanCode*HC,intn)/*赫夫曼编码,放入HC中*/
{
inti,start,c,f;
char*cd;
(*HC)=(HuffmanCode)malloc((n+1)*sizeof(char*));
cd=(char*)malloc(n*sizeof(char));/*编码的空间*/
cd[n-1]='\0';/*编码结束符号*/
for(i=1;i<=n;++i)/*逐个叶子结点求编码*/
{
start=n-1;/*结束位置*/
for(c=i,f=HT[i].parent;f!
=0;c=f,f=HT[f].parent)
{
/*从叶子到根求编码*/
if(HT[f].lchild==c)
{
cd[--start]='0';
}
else
{
cd[--start]='1';
}
}
/*为第i个叶子结点求空间*/
(*HC)[i]=(char*)malloc((n-start)*sizeof(char));
strcpy((*HC)[i],&cd[start]);/*从cd复制到HC*/
}
}
voidPrintHuffmanCode(HuffmanCodeHC,unsignedint*w,intn)/*打印编码*/
{
inti;
printf("\n*********Huffman********\n\n");
printf("theHuffmanCodeis:
\n\n");
for(i=1;i<=n;i++)
{
printf("%3d---",w[i-1]);/*先打印权值*/
printf("%s",HC[i]);/*打印表*/
printf("\n");
}
}
6.用户使用说明
1,输入总叶子节点数,也就是需要编码的个数.
2,输入每个叶子节点所带的权值,需要根据权值计算并生成霍夫曼编码.
7.测试结果
1.输入结果:
2.输出结果:
<二>.Joseph约瑟夫环
1.问题描述:
编号为1、2、……、n的n个孩子围坐一圈,任选一个数m,从第一个孩子开始数,数到m停止,这个孩子离开,再从第一个开始数,直到剩下一个孩子。
最最后剩下的孩子就是赢家。
2.需求分析
(1)输入的形式和输入值的范围:
输入值为整数,且任选一个位置的数要小于孩子数。
(2)输出的形式:
从屏幕显示游戏过程排列,出来的孩子顺序,和最后的赢家。
(3)程序所能达到的功能:
提供用户从键盘输入,Joseph约瑟夫环的必要数据,并显示获胜者号。
(4)测试数据:
正确的数据如下图显示,错误的数据时,number:
1,began:
2,count:
1,2,1
结果:
badbeginposition
badintervalnumber
2.概要设计
1,函数说明:
intassign();功能:
赋初值,返回1:
成功,0:
失败
voidinitial(Jose*pBoys);功能:
初始化环链表
voidcount(intm);功能:
数m个小孩
voidprocess();功能:
处理所有未获胜小孩
2.本程序包含以下模块:
(1)主程序模块:
main(void)
{
输入数据;
执行功能;
显示结果;
}
(2)各功能模块——实现Joseph编码的各项功能。
各模块的调用关系:
4.详细设计:
#include
#include
structJose{//小孩结构
intcode;//存放小孩编号
Jose*next;//用于指向下一个小孩结点
};
//全局变量
intn;//小孩数
intbegin;//开始位置
intm;//数小孩间隔
Jose*pivot;//链表哨兵
Jose*pCur;//当前结点指针
//函数声明
intassign();//赋初值,返回1:
成功,0:
失败
voidinitial(Jose*pBoys);//初始化环链表
voidcount(intm);//数m个小孩
voidprocess();//处理所有未获胜小孩
//主函数
voidmain()
{
if(!
assign()){
cout<<"Theprogramfailed.\n";
return;
}
Jose*pJose=newJose[n];//分配结构数组
initial(pJose);//初始化结构数组
count(begin);//转到开始位置
process();//处理所有未获胜小孩
cout<<"\n\n*******Josephus**result*************:
\n\n";
cout<<"\nthewinneris"<code<delete[]pJose;//返还结构数组给堆空间
}
//赋初值
intassign()
{
intnumber,start,count;
cout<<"*******Josephus**input*************:
\n\n";
cout<<"pleaseinputthekidsnumber:
\n";//输入孩子数,开始位置和间隔数
cin>>number;
cout<<"pleaseinputthebeginposition:
\n";
cin>>start;
cout<<"pleaseinputtheintervalnumber:
\n";
cin>>count;
if(number<2){//小孩数校验
cerr<<"\nbadnumberofboys";
return0;
}
if(start<0){//开始位置校验
cerr<<"badbeginposition.\n";
return0;
}
if(count<1||count>number){//数小孩个数校验
cerr<<"badintervalnumber.\n";
return0;
}
n=number;begin=start;m=count;//赋全局变量值
return1;
}
//链表初始化
voidinitial(Jose*pJose)
{
intl=0;
Jose*px=pJose;
cout<<"\n*******Josephus**process************:
\n";
for(inti=1;i<=n;i++){
px->next=pJose+i%n;
px->code=i;
px=px->next;
if((l++%10)==0)//输出行中个数控制
cout<cout<}
cout<pCur=pJose+n-1;//指向结构数组最后一个元素
}
//数m个小孩
voidcount(intm)
{
for(inti=0;ipivot=pCur;
pCur=pivot->next;
}
}
//处理获胜者决出之前的所有小孩
voidprocess()
{
intl=0;
for(inti=1;icount(m);//数m个小孩
if((l++%10)==0)//输出行中个数控制
cout<cout<code;
pivot->next=pCur->next;//小孩脱链
pCur=pivot;
}
}
5,用户使用说明
1;输入要参加游戏的孩子数
2;输入要成为开始点的孩子位置
3;输入每次被数的孩子间隔数
注意:
不要把位置数大于孩子数,和定义间隔的数超过孩子数,如,孩子数是3,间隔数为2,2,2,2;
6,测试结果
输入结果:
输出结果:
<三>调试分析
1.Huffman编码器
1,过程的调试:
编码是默认为二元编码,建立赫夫曼树,w存放权值,在每次把两个小的权值相加后,在每次select中都能包括进去新的结点每次父亲结点被重新赋值,不为0在每次select中除去。
存在的问题,设计的不够详细,只能简单实现编码,无法真正做到全面细致的编码过程,还有一些C语言语法和结构体调用的问题,已在编码时解决。
1.2,时间复杂度为:
n,因为都只是单循环
1.3,好的设想:
定义需要调用的几个函数,需要输入信源数,来选择需要编码的范围,还要建立一个函数用来判断需要编码的个数,并选择需要压缩的次数,需要虚码0来补数M个,通过来计算M,如果M其中:
a:
需编码的个数,r:
为信源,k=int(
).
2.Joseph约瑟夫环
2.1.调试过程:
在调试过程中,遇到的问题就是当输入的开始位置数和间隔的总数大于孩子数的时候,就不会输出,会跳出来。
这个问题可以用一个IF句,提到,显示badnumberofboys;badbeginposition;badintervalnumber来提示用户,还有一个问题,当输出完毕后会直接跳出,如果还想输入需要重新运行,可以加一个循环给主函数,来实现重复输入输出的功能。
最后一个问题是,胜利者前面的出去的小孩没有输出。
2.2,时间复杂度为:
n,因为都只是单循环
2.3,好的设想:
算法更精简些,输出的更详细些,这个算法基本比较完善了。
<四>.心得体会:
通过这次课程设计,发现了代码的知识是对我很大的历练,不论开始的结构体定义还是后面的指针,都是需要很强的逻辑能力。
首先,编码之前,要画流程图,不能急于编码,要先把这方面的知识理清,把逻辑上的循环的指针指向也理清,其次是编码,怎样应用简单明了的方法把代码编出,怎么以一个程序员的角度为用户着想,让他们更明白的应用我们的程序,还有编程序时候的格式和排版也很重要,一个清晰明了的排版,无论是他人检查,浏览,还是自己改错都是很方便的。
还有就是调试的过程中,出现的很多错误,没有人是天生不犯错的,我们只能避免少犯错,但不要因为犯错而气馁,而急躁,一个好的程序,不仅讲求的是效率,更讲求的是质量。
<五>.参考文献
1.信息论与编码理论沈世镒陈鲁生编写科学出版社出版发行
2.数据结构C语言版严蔚敏清华大学出版社