课设说明书杨开亮.docx
《课设说明书杨开亮.docx》由会员分享,可在线阅读,更多相关《课设说明书杨开亮.docx(36页珍藏版)》请在冰豆网上搜索。
课设说明书杨开亮
*******************
实践教学
*******************
兰州理工大学
计算机与通信学院
2015年秋季学期
算法与数据结构课程设计
题目:
哈夫曼编\译码系统
宾馆客房管理系统
专业班级:
软件工程
(2)班
姓名:
杨开亮
学号:
1416270214
指导教师:
张永
成绩:
________________
目录
摘要3
一.哈夫曼编\译码系统4
1.采用类语言定义相关的数据类型4
2.算法设计5
3.函数的调用关系图5
4.调试分析9
5.测试结果9
6.源程序(带注释)12
二.宾馆客房管理系统20
1.采用类语言定义相关的数据类型20
2.算法设计20
3.函数的调用关系图20
4.调试分析22
5.测试结果22
6.源程序(带注释)24
总结30
参考文献31
致谢32
摘要
Huffman编码是一种可变长编码方式,是二叉树的一种特殊转化形式。
它的原理是:
将使用次数多的代码转换成长度较短的编码,而使用次数少的可以使用较长的编码,并且保持编码的唯一可解性。
本文根据Huffman编码原理,在详细设计中,根据权值和最小的根本原则,我们输入要编码的字符集及其它的权值,再根据在概要设计中提到的节点Node类,算法SuanFa类以及主类JieMian类,建立哈夫曼树,并进行编码,最后输出哈夫曼编码。
在完成Huffman编码后,我们利用其构建的哈夫曼编码树来进行译码。
与编码过程不同,译码过程中,我们将用户输入的二进制代码串依次与字符集中的每个字符的编码进行比较,译出一个字符后,循环比较下一个字符的编码,直到所有二进制码全部译出为止。
在编码和译码的过程中,我们遇到很多问题,诸如算法、语法问题,但我们都通过不断的分析,和调试将这些问题一一解决,最终建立了一个完整的编/译
近年来,宾馆业迅猛发展,市场的竞争日趋激烈,全面提高宾馆的软件管理水准,已成为宾馆业发展的当务之急。
尤其是对于星级宾馆,既需要完成前台的一些服务工作,还需要完成后台的管理工作。
然而,传统的人工管理模式已经远远不能满足有效、快捷地处理经营中产生的大量信息数据的需要,从而使得企业决策层无法及时、准确地掌握一线资料,继而影响对市场进行正确地分析和预测。
像沿海城市三星级以上宾馆引进外方管理,使小部分宾馆管理水准几乎接近或达到国际水平。
但对占80%以上的广大中小型宾馆来说,是难以做到的。
因此,欲在竞争中甩开对手,取得优势,必须在经营、管理、产品、服务等方面具备独到之处。
而对宾馆的经营状况起决定作用的是客房的管理。
简单的服务标准已不是制胜的锦囊,只有管理做到最细微之处,才能让顾客体会到宾馆服务的高标准、高质量,而准确、快速、周全往往就是最基本的成功要素。
传统的管理方法已经不能适应现代社会的需要,因此采用电脑管理业务、财务等诸多环节已成为推动宾馆业迅速发展的先决条件,宾馆客房管理信息系统是各大中小型宾馆所需要使用的一个管理系统。
关键词:
关键词:
Huffman编码树;最优二叉树;编码;译码;宾馆客房;管理;顺序遍历;模块。
一.哈夫曼编译码系统
利用赫夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。
这要求在发送端通过一个编码系统对待传输数据预先编码,在接收端将传来的数据进行译码(复原)。
对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
试为这样的信息收发站编写一个赫夫曼码的编/译码系统。
哈夫曼编码(HuffmanCoding)是一种编码方式,以哈夫曼树─即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。
是指使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。
这种方法是由David.A.Huffman发展起来的。
例如,在英文中,e的出现概率很高,而z的出现概率则最低。
当利用哈夫曼编码对一篇英文进行压缩时,e极有可能用一个位(bit)来表示,而z则可能花去25个位(不是26)。
用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个位。
二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。
倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。
1.采用类语言定义相关的数据类型
typedefstruct
{
unsignedintweight;
unsignedintparent,lchild,rchild;
}HTNode,*HuffmanTree;
intweight;
intparent;
intlchild;
intrchild;
}Hnodetype;
typedefstruct{
intbit[Maxbit];
intstart;
}Hcodetype;
intn=0;
voidinputfun(Hnodetypehuffnode[Maxnode])//输入叶子节点的个数及权值:
初始化函数
2.算法设计
1.构造哈夫曼树,使用静态链表作为哈夫曼树的存储
在构造哈夫曼树时,设计一个结构体数组Huffnode来保存哈夫曼树的各个结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组Huffnode的大小设置为2n-1,在实际设计过程中,定义符号常量Maxleaf,为最大的叶节点的个数,然后再定义一个符号常量Maxnode为Maxleaf*2-1,代表最大的总的结点的个数。
2.求哈夫曼编码时使用一维结构数组Huffcode作为哈夫曼编码信息的存储。
求哈夫曼编码,实质上就是在已建立的哈夫曼树中,从叶子结点开始,沿叶结点的双亲链域回退到根结点,每回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值。
由于一个字符的哈夫曼编码是从根结点到相应叶结点所经过的各个分支所组成的0,1序列,因此先得到的分支代码为所求代码的低位码,后得到的分支代码为所求编码的高位码。
3.采用文件读写的方式读取结点信息,存入结点信息,减少传递参数带来的不便,且同时将数据信息有效的保存起来。
3.函数的调用关系图
4.调试分析
a、调试过程中遇到的问题主要是对部分变量的定义不明确导致程序在运行时不能理解该变量的意义,还有就是刚开始设计函数时是按照功能模块来设计的,所以在最后的代码调试阶段出现大量的功能模块融入不到一块的问题。
解决这些问题主要是通过阅读相关的文献重新学习C语言而解决的。
b、算法的时间复杂度和空间复杂度都是O(nlogn)。
5.测试结果
1.初始化函数
2.输出函数
2.1输出各个结点的权重、左孩子、右孩子、双亲结点的下标的编码表及叶结点的字符对应编码的编码情况
3.译码函数
4.此时的4个文本文件
6.源程序(带注释)
inti;
charzifu[10];
ofstreamin;
in.open("data1.txt",ios:
:
trunc);
cout<<"请输入叶子节点的个数";
cin>>n;
while(n<=0||n>20)
{
cout<<"输入错误,请重新输入";
cin>>n;
}
in<for(i=0;i<2*n-1;i++)
{
huffnode[i].weight=0;
huffnode[i].parent=-1;
huffnode[i].lchild=-1;
huffnode[i].rchild=-1;
}
cout<<"请分别输入这"<for(i=0;i{
cout<cin>>zifu[i];
in<cout<<"权重-";
cin>>huffnode[i].weight;
in<}
in.close();
}
voidcreattree(Hnodetype*huffnode)//哈夫曼树的建立
{
intm1,m2,x1,x2,n;
inti,j;
fstreamout1;
out1.open("data1.txt",ios:
:
in);
out1>>n;
out1.close();
for(i=0;i{
m1=m2=Maxvalue;
x1=x2=0;
for(j=0;j{
if(huffnode[j].parent==-1&&huffnode[j].weight{
m2=m1;
x2=x1;
m1=huffnode[j].weight;
x1=j;
}
else
if(huffnode[j].parent==-1&&huffnode[j].weight{
m2=huffnode[j].weight;
x2=j;
}
}
huffnode[x1].parent=n+i;
huffnode[x2].parent=n+i;
huffnode[n+i].weight=huffnode[x1].weight+huffnode[x2].weight;
huffnode[n+i].lchild=x1;
huffnode[n+i].rchild=x2;
}
ofstreamin;
in.open("data2.txt",ios:
:
trunc);
for(i=0;i<2*n-1;i++)
{
in<<<<}
in.close();
}
voidoutput2()//输出编码表:
权重、左孩子、右孩子及双亲的下标地址
{
inta,b,c,d,m;
fstreamout1;
out1.open("data1.txt",ios:
:
in);
out1>>m;
out1.close();
fstreamout;
out.open("data2.txt",ios:
:
in);
for(inti=0;i<2*m-1;i++)
{
out>>a>>b>>c>>d;
cout<}
out.close();
}
voidcodefun()//哈夫曼编码函数
{
Hcodetypecd;
Hcodetypehuffcode[Maxleaf];
Hnodetypehuffnode[Maxnode];
inti,j,c,p,n;
fstreamout1;
out1.open("data1.txt",ios:
:
in);
out1>>n;
out1.close();
fstreamout2;
out2.open("data2.txt",ios:
:
in);
for(i=0;i<2*n-1;i++)
{
out2>>huffnode[i].weight
>>huffnode[i].lchild
>>huffnode[i].rchild
>>huffnode[i].parent;
}
for(i=0;i{
cd.start=n-1;
c=i;
p=huffnode[i].parent;
while(p!
=-1)
{
if(huffnode[p].lchild==c)
cd.bit[cd.start]=0;
else
cd.bit[cd.start]=1;
cd.start--;
c=p;
p=huffnode[c].parent;
}
for(j=cd.start+1;j{
huffcode[i].bit[j]=cd.bit[j];
huffcode[i].start=cd.start;
}
}
out2.close();
ofstreamin;
in.open("data3.txt",ios:
:
trunc);
for(i=0;i{
in<for(intj=huffcode[i].start+1;jin<in<}
in.close();
}
voidoutputcode()//输出哈夫曼编码:
形式为A--010
{
chars;
intw;
intm,b,d;
fstreamout1;
out1.open("data1.txt",ios:
:
in);
fstreamout2;
out2.open("data3.txt",ios:
:
in);
out1>>m;
for(intc=0;c{
out1>>s>>w;
cout<
out2>>b;
for(intr=b+1;r{
out2>>d;
cout<}
cout<}
out1.close();
out2.close();
}
voidencode()//哈夫曼解码函数
{
chara[100];
charzifu[30];
intlen,cc,n,w;
intj=0;
intp,c=0,mm;
Hnodetypehuffnode[Maxnode];
Hcodetypehuffcode[Maxleaf];
fstreamout1;
out1.open("data1.txt",ios:
:
in);
out1>>n;
for(intv=0;v>zifu[v]>>w;
out1.close();
fstreamout2;
out2.open("data2.txt",ios:
:
in);
for(v=0;v<2*n-1;v++)
{
out2>>huffnode[v].weight
>>huffnode[v].lchild
>>huffnode[v].rchild
>>huffnode[v].parent;
}
out2.close();
fstreamout3;
out3.open("data3.txt",ios:
:
in);
for(v=0;v{
out3>>huffcode[v].start;
for(intu=huffcode[v].start+1;uout3>>huffcode[v].bit[u];
}
out3.close();
ofstreamin;
in.open("data4.txt",ios:
:
trunc);//ios:
:
trunc表示在打开文件前将文件清空,文件不存在则创建
cout<<"请输入一串二进制编码"<cin>>a;
len=strlen(a);
p=huffnode[c].parent;
while(p!
=-1)
{
c++;
p=huffnode[c].parent;
}//求树中结点的总数目为c,根节点在huffnode[]中的下表地址为c
cc=c;//记录当前的下表地址
cout<<"译码结果为";
for(inti=0;i{
if(a[i]=='0')cc=huffnode[cc].lchild;
elseif(a[i]=='1')cc=huffnode[cc].rchild;
if(huffnode[cc].lchild==-1&&huffnode[cc].rchild==-1)//从j到i为一个字符的编码
{
for(intk=0;k{
mm=huffcode[k].start+1;
for(inthh=j;hh<=i,mm{
if((a[hh]-'0')!
=huffcode[k].bit[mm])break;
}
if(hh>=i&&mm==n)
{
cout<in<j=i+1;
cc=c;//更新j和cc的值
break;
}
}
}
}
in.close();
}
intmain()
{
intm,n;
Hnodetypehuffnode[Maxnode];
cout<cout<<"1.建立哈夫曼树"<<<"2.输出哈夫曼编码"<<<"3.进行哈夫曼译码"<<<"0.退出"<<<"请选择:
";
cin>>m;
while(m<0||m>3)
{
cout<<"输入错误,请重新输入";
cin>>m;
}
while(m)
{
fstreamout1;
out1.open("data1.txt",ios:
:
in);
out1>>n;
out1.close();
if(m==1)
{
inputfun(huffnode);
creattree(huffnode);
codefun();
}
elseif(m==2)
{
if(n==0)
{
cout<<"请先初始化,建立哈夫曼树"<}
else
{
cout<output2();
cout<outputcode();
}
}
elseif(m==3)
{
if(n==0)
{
cout<<"请先初始化,建立哈夫曼树"<}
else
{
encode();
cout<}
}
cout<<"返回主菜单为"<cout<cout<<"1.建立哈夫曼树"<<<"2.输出哈夫曼编码"<<<"3.进行哈夫曼译码"<<<"0.退出"<<<"请选择:
";
cin>>m;
while(m<0||m>3)
{
cout<<"输入错误,请重新输入";
cin>>m;
}
}
return0;
}
二.宾馆客房管理系统
1.采用类语言定义相关的数据类型
structNode
{
intCount;//指示该房间有多少个房客
charnameOne[20];//房客1的名字
charnameTwo[20];//房客2的名字
intsexOne;//房客1的性别-1代表女,0代表没有,1代表男
intsexTwo;//房客2的性别
introomNumber;//房间号
}roomArray[5];
2.算法设计
1.这是一个小型的管理系统,使用结构体数组存储客房的信息。
2.一般的管理系统都应该具备插入,修改,查询,删除,浏览,排序,统计,追加等功能,通过使用一个简易菜单进行执行动作的选择。
3.用函数实现模块化设计,调理清晰,使程序易读写。
4.把程序与文件联系,使数据能存储在磁盘中,更具实用性。
3.函数的调用关系图
4.调试分析
a.在调试过程中的主要问题为程序没有与文件建立联系,所进行的的操作结果在程序运行结束后不能保存,所以等下次重新打开程序是之前的数据将会丢失。
B.通过对该程序的各项操作的分析:
旅客入住,信息查询,旅客入住,信息插入,信息追加,信息删除的时间复杂度都为O
(1),而信息排序,信息统计的时间复杂度为O(n2),所以综合上述操作的时间复杂度为O(n2)。
5.测试结果
1.这是主操作页面调试图
2.这是进行旅客入住操作图
3.这是对已入住旅客信息查询操作图
6.源程序(带注释)
//初始化房间数组
voidInitArray()
{
inti;
for(i=0;i<5;i++)
{
roomArray[i].roomNumber=301+i;
memset(roomArray[i].nameOne,0,20);
memset(roomArray[i].nameTwo,0,20);
roomArray[i].sexOne=0;
roomArray[i].sexTwo=0;
roomArray[i].Count=0;
}
}
voidfun1()//旅客入住的操作
{
charname[20];
intsex;
inti;
printf("\n输入入住旅客姓名和性别(空格隔开,1为男,-1为女):
");
scanf("%s%d",name,&sex);
for(i=0;i<5;i++)
{
if(roomArray[i].Count==2)
{
continue;
}
elseif(roomArray[i].Count==1)
{
if(roomArray[i].sexOne!
=sex)
{
continue;
}
strcpy(roomArray[i].nameTwo,n