数据结构课程设计报告(农夫过河)

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数据结构课程设计报告(农夫过河)
第一篇:数据结构课程设计报告(农夫过河)
目录
引言...................................................2 问题描述..............................................3 基本要求 (3)
2.1为农夫过河问题抽象数据模型体会数据模型在问题求解中的重要性;........3 2.2设计一个算法求解农夫过河问题,并输出过河方案;......................3 3 概要设计 (3)
3.1 数据结构的设计。

....................................................3 3.1.1农夫过河问题的模型化.............................................3 3.1.2 算法的设计 (4)
4、运行与测试 (6)
5、总结与心得..........................................7 附录...................................................7 参考文献. (13)
引言
所谓农夫过河问题是指农夫带一只狼、一只羊和一棵白菜在河南岸, 需要安全运到北岸。

一条小船只能容下他和一件物品, 只有农夫能撑船。

问农夫怎么能安全过河, 当然狼吃羊, 羊吃白菜, 农夫不能将这两种或三种物品单独放在河的一侧, 因为没有农夫的照看, 狼就要吃羊, 而羊可能要吃白菜? 这类问题的实质是系统的状态问题, 要寻求的是从初始状态经一系列的安全状态到达系统的终止状态的一条路径。

1 问题描述
一个农夫带一只狼、一棵白菜和一只羊要从一条河的南岸过到北岸,农夫每次只能带一样东西过河,但是任意时刻如果农夫不在场时,狼要吃羊、羊要吃白菜,请为农夫设计过河方案。

基本要求
2.1为农夫过河问题抽象数据模型体会数据模型在问题求解中的重要性;2.2设计一个算法求解农夫过河问题,并输出过河方案;概要设计
3.1 数据结构的设计。

3.1.1农夫过河问题的模型化分析这类问题会发现以下特征: 有一组状态(如农夫和羊在南, 狼和白菜在北);从一个状态可合法地转到另外几个状态(如农夫自己过河或农夫带着羊过河);有些状态不安全(如农夫在北, 其他东西在南);有一个初始状态(都在南);结束状态集(这里只有一个, 都在北)。

问题表示: 需要表示问题中的状态, 农夫等位于南P北(每个有两种可能)。

可以采用位向量, 4 个二进制位的0P1 情况表示状态, 显而易见, 共24= 16种可能状态。

从高位到低位分别表示农夫、狼、白菜和羊。

0000(整数0)表示都在南岸, 目标状态1111(即整数15)表示都到了北岸。

有些状态0011,0101, 0111, 0001, 1100, 1001 是不允许出现的, 因为这些状态是不安全状态。

根据上述条件可以画出系统的状态图如图1 所示。

图1 系统状态转换图
其中双向的箭头表示状态可逆, 即农夫可以带
着某种东西过去, 也可以带着该东西回来。

箭头上的字母表示农夫所携带的东西: f(farmer), w(wolf), g(goat), c(cabbage)分别表示农夫自己、农夫携带狼、农夫携带羊、农夫携带菜过河。

现在的问题转化为: 找一条合法路径(相邻状态之间的转移合法), 从开始状态到某个结束状态, 途中不经过不安全状态。

3.1.2 算法的设计
求农夫、狼、白菜和羊的当前状态的函数为每一种状态做测试, 状态安全则返回0, 否则返回1。

安全性判断函数, 若状态安全则返回0 int farmer(int location)//判断农夫位置对0做与运算,还是原来的数字,用来判断位置{ return 0!=(location & 0x08);} int wolf(int location)//判断狼位置 { } int cabbage(int location)//判断白菜位置{ return 0!=(location & 0x02);} int goat(int location)//判断羊的位置 { return 0!=(location & 0x01);} int safe(int location)// 若状态安全则返回 true {
if((goat(location)== cabbage(location))&&(goat(location)!= return 0;farmer(location)))if((goat(location)==
wolf(location))&&(goat(location)!= return 0;return 0!=(location & 0x04);farmer(location)))return 1;//其他状态是安全的
借助于位向量和按位运算符, 很容易描述过河动作, 这种问题表示的设计使得程序的实现比较容易。

算法的基本思想: 利用队列moveT o 记录可到的尚未向前探试的状态, 数组元素route [ i] 记录状态i的路径[ 前一状态] ,1)){ 从moveTo 取出一个状态;试探所有由这个状态出发可能到达的状态;if(能到达的状态安全且未访问过){ 记录到它的路径;压入队列;} } } 精化上速算法得到问题的具体算法如下: void farmerProblem(){
int movers, i, location, newlocation;int route[16];//记录已考虑的状态路径int print[MAXNUM];PSeqQueue moveT o;moveTo = createEmptyQueue_seq();//新的队列判断路径enQueue_seq(moveTo, 0x00);//初始状态为0 for(i = 0;i < 16;i++) route[i] =-1;//-1表示没有记录过路径route[0]=0;while(!isEmptyQueue_seq(moveT o)&&(route[15]==-1))//队列不为空,路径未 { location = frontQueue_seq(moveT o);//从队头出队,location表示位置,0 deQueue_seq(moveTo);//已出队的删除满时循环
为北岸,1为南岸
for(movers = 1;movers <= 8;movers<<= 1)//向左移位,movers分别0001,0010,0100,1000,也就是依次判断过河的可行性 { if((0!=(location & 0x08))==(0!=(location & movers)))//判断 { 农夫和要移动的物品是否在同岸
newlocation = location^(0x08|movers);//过岸
if(safe(newlocation)&&(route[newlocation] ==-1))//判断是否安全,以及路径是否可用
{ route[newlocation] = location;enQueue_seq(moveTo, newlocation);//记录路径并入队,位置改

4、运行与测试
5、总结与心得
“纸上得来终觉浅,绝知此事要躬行。

”通过这两周的课程设计,使我对书上的的理论知识有了更深的理解,也使我对于团队合作有了新的认识,意识到团队的力量。

课程设计是一个必须经历的过程,是我们理解书本知识、熟悉所学专业的一次很好实践。

在这次设计过程中,体现出自己单独设计程序的能力以及综合运用知识的能力,体会了学以致用、突出自己劳动成果的喜悦心情,从中发现自己平时学习的不足和薄弱环节,从而加以弥补。

附录
#include #include #define MAXNUM 20 typedef struct //顺序队列类型定义 { int f, r;//f表示头,r 表示尾
int q[MAXNUM];//顺序队
}SeqQueue ,*PSeqQueue;
PSeqQueue createEmptyQueue_seq()//创建队列{ PSeqQueue paqu = new SeqQueue;if(paqu == NULL) cout<<“Out of space!”<f=paqu->r=0;return(paqu);} int isEmptyQueue_seq(PSeqQueue paqu)//判断 paqu 所指是否是空队列{ return paqu->f==paqu->r;} void enQueue_seq(PSeqQueue paqu,int x)//在队列中插入一元素 x {
} if((paqu->r+1)%MAXNUM==paqu->f){
}
paqu->q[paqu->r]=x;paqu->r=(paqu->r+1)%MAXNUM;cout<<“队列已满.”<
} int frontQueue_seq(PSeqQueue paqu)//对非空队列,求队列头部元素 { } int farmer(int location)//判断农夫位置对0做与运算,还是原来的数字,用来判断位置{ return 0!=(location & 0x08);} int wolf(int location)//判断狼位置 { } int cabbage(int location)//判断白菜位置 { return 0!=(location & 0x02);} int goat(int location)//判断羊的位置 {
if(paqu->f==paqu->r)cout<<“队列为
空”<f=(paqu->f+1)%MAXNUM;else return(paqu->q[paqu->f]);return 0!=(location & 0x04);return 0!=(location & 0x01);} int safe(int location)// 若状态安全则返回true {
} void farmerProblem(){
int movers, i, location, newlocation;int route[16];//记录已考虑的状态路径int print[MAXNUM];if((goat(location)== cabbage(location))&&(goat(location)!= return 0;farmer(location)))if((goat(location)==
wolf(location))&&(goat(location)!= return 0;farmer(location)))return 1;//其他状态是安全的
PSeqQueue moveT o;moveT o = createEmptyQueue_seq();//新的队列判断路径enQueue_seq(moveT o, 0x00);//初始状态为0 for(i = 0;i < 16;i++)
route[i] =-1;//-1表示没有记录过路径route[0]=0;while(!isEmptyQueue_seq(moveT o)&&(route[15]==-1))//队列不为空,路径未 { location = frontQueue_seq(moveT o);//从队头出队,location表示位置,0 deQueue_seq(moveTo);//已出队的删除满时循环
为北岸,1为南岸
for(movers = 1;movers <= 8;movers<<= 1)//向左移位,movers分别0001,0010,0100,1000,也就是依次判断过河的可行性 { if((0!=(location & 0x08))==(0!=(location & movers)))//判断 { 农夫和要移动的物品是否在同岸
newlocation = location^(0x08|movers);//过岸
if(safe(newlocation)&&(route[newlocation] ==-1))//判断是否安全,以及路径是否可用
{ route[newlocation] = location;enQueue_seq(moveTo, newlocation);//记录路径并入队,位置改

}
}
}
} /* 打印出路径 */ if(route[15]!=-1){
cout<<“过河步骤是: ”<
i=0;
for(location = 15;location >= 0;location = route[location]) {
print[i]=location;
i++;
if(location == 0)
break;
}
int num=i-1;int temp[20][4];
int j;
for(i=num;i>=0;i--)
{
for(j=3;j>=0;j--){
}
} temp[num-i][j]=print[i]%2;print[i]/=2;temp[0][j]=0;temp[num+1][j]=1;/* for(i=0;i<=num;i++){
for(j=0;j<4;j++)cout<
cout<<“tttNO.”<
if(temp[i][3]!=temp[i-1][3])
cout<<“农夫带羊过南岸”;
if(temp[i][2]!=temp[i-1][2])cout<<“农夫带白菜过南岸”;cout<<“农夫带狼过南岸”;if(temp[i][1]!=temp[i-1][1]) if(temp[i][3]==temp[i-1][3]&&temp[i][2]==temp[i-
1][2]&&temp[i][1]==temp[i-1][1])
} cout<<“农夫自己过南岸”;else if(i%2==0){ if(temp[i][3]!=temp[i-1][3])cout<<“农夫带羊回北岸”;
if(temp[i][2]!=temp[i-1][2])
cout<<“农夫带白菜回北岸”;cout<<“农夫带狼回北岸”;if(temp[i][1]!=temp[i-1][1])if(temp[i][3]==temp[i-1][3]&&temp[i][2]==temp[i-1][2]&&temp[i][1]==temp[i-1][1]) cout<<“农夫自己回北岸”;
}
cout<
} }
else cout<<“No solution.”<
return 0;}
参考文献
1.王红梅、王涛、胡明编著。

数据结构。

北京:清华大学出版社出版,2011.6
2.王红梅编著。

算法设计与分析。

北京:清华大学出版社,2006
第二篇:数据结构课程设计报告
青岛理工大学
数据结构课程设计报告
题目:宿舍管理查询软件
院(系):计算机工程学院
学生姓名:谢茂盛
班级:网络121学号: 201207131
起迄日期:2014.07.07-2014.07.20
指导教师:张艳
一、需求分析(所有大标题宋体加粗四号,下同)(小标题宋体加粗小四,下同)
1.问题描述:
以无歧义的陈述详细说明对自己所选题目的解释性描述,可以补
充说明该设计中要做的具体任务。

强调的是程序要做什么?
2.基本功能
要求分别列出该设计要实现的功能,(每个功能要尽量和概要设计中的模块函数对应起来)。

二、概要设计
1.设计思路:
解决问题的思路概述,拟采用的算法的简介。

2.数据结构设计:
要求分别列出拟采用的数据结构及其定义,分为逻辑结构(线性?树状?图状?)和存储结构(顺序?链式?)。

采用该结构的原因,如果有定义的抽象数据类型,可以列出其定义及各种操作。

如下为抽象数据类型定义的模板。

定义程序中用到的抽象数据类型;
设计中所用到的数据结构或抽象数据类型的说明,以及在程序中的作用
抽象数据类型线性表的定义如下:
ADT List{
数据对象:D={ai| ai ∈ElemSet,i=1,2,3……,n,n≥0}
数据关系:R1={| ai-1,ai ∈D,i=1,2,3,……,n}
基本操作:
Insert(&L,i,j)
初始条件:线性表L已存在,1≤i≤n+1。

操作结果:在L中第i个位置之前插入新的数据元素j,L的长度加1。

Del(&L,i,j)
初始条件:线性表L已存在,1≤i≤n。

操作结果:删除L的第i个数据元素,L的长度减1
Xg(&L,i,j)
初始条件:线性表L已存在。

操作结果:用新的输入数据项j代替原有的指定要修改的数据项i。

Search(&L,i,e)
初始条件:线性表L已存在。

操作结果:查找指定的某元素i,并将值赋给e,用e 输出。

}
3.软件结构设计:
按需求分析中的功能进行模块划分,建立模块的层次结构及调用关系。

三、详细设计
实现概要设计中定义的所有数据类型,对每个操作只需要写出伪代码算法;对主程序和其他模块也都需要写出伪代码算法(伪代码算法达到的详细程度建议为:按照伪代码算法可以在计算机键盘直接输入高级程序设计语言程序));可采用流程图、活动图进行描述,画出函数和过程的调用关系图。

实现设计中主程序和其他子模块的算法,以流程图的形式表示,需画出函数和过程的调用关系图。

本小节内所有的图均要求用Visio或Word进行绘制,不允许用bmp或其他格式的图片。

绘图内文字均采用宋体五号(如果图比较大,排版不好看的话,可以根据需要缩小字体),单倍行间距,段前段后均设置为0行。

1.定义程序中所有用到的数据及其数据结构,及其基本操作的实现;
2.主函数和其他函数的伪码算法;
3.主要函数的程序流程图,实现设计中主程序和其他子模块的算法,以流程图的形式表示。

4.画出函数之间的调用关系图。

四、调试分析
内容包括:调试过程中遇到的问题是如何解决的以及对设计与实现的回顾讨论和分析。

1.实际完成的情况说明(完成的功能,支持的数据类型等);
2.程序的性能分析,包括时空分析;
3.上机过程中出现的问题及其解决方案;
4.程序中可以改进的地方说明;
5.程序中可以扩充的功能及设计实现假想。

五、测试结果
列出你的测试结果,包括输入和输出。

注意测试数据应该完整和严格,至少给出2组测试结果(含合法数据与非法数据)。

六、用户手册
说明如何使用你编写的程序,详细列出每一步的具体操作步骤。

这里可以有适当的运行结果抓图。

用户手册与开发过程无关,只与使用有关,必须是Step by Step的。

所有运行结果截图均要求有实际数据的内容,截图尺寸要求按页宽排版两张大小,且要求有每张图下面有规范的标题说明如何使用你编写的程序,详细列出每一步的操作步骤。

七、体会与自我评价
写出本设计的总结思考,收获心得体会,要求不少于600字,不得摘抄网上资料,只能参考。

正文(各标题除外),均采用宋体和Times New Roman字体,小四号字,1.25倍行距。

八、参考文献(列出你参考的书,格式按照下面的例子来写)例如:
[1]严蔚敏.数据结构(C语言).清华大学出版社,2007
第三篇:数据结构课程设计报告
数据结构课程设计
散列表的应用:插队买票
专业计算机科学与技术(网络技术)
金玲计算机131 1310704114 张静林 2015年1月23日学生姓名班学级号
指导教师完成日期
目录概述……………………………………………………………………………………1 1.1 课
程设计目的……………………………………………………………………….1 1.2 课程设计内容……………………………………………………………………….1 2 系统需求分析……………………………………………………………………….1 2.1 主体功能…………………………………………………………………………....2 3系统概要设计…………………………………………………………………………2 3.1 系统流程图………………………………………………………………………….2 4 系统详细设计…………………………………………………………………………3 5 测试……………………………………………………………………………………5 5.1 测试方案…………………………………………………………………………….5 5.2 测试结果…………………………………………………………………………….5 6 小结……………………………………………………………………………………5 参考文献…………………………………………………………………………………5 附录………………………………………………………………………………………7 附录1 源程序清单……………………………………………………………………...7 概述
1.1 课程设计目的
数据结构课程设计是为数据结构课程独立开设的实践性教学环节。

数据结构课程设计对于巩固数据结构知识,加强学生的实际动手能力和提高学生综合素质是十分必要的。

课程设计的目的:
1.要求学生达到熟练掌握C语言的基本知识和技能。

2.了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力。

3.提高程序设计和调试能力。

学生通过上机实习,验证自己设计的算法的正确性。

学会有效利用基本调试方法,迅速找出程序代码中的错误并且修改。

4.培养算法分析能力。

分析所设计算法的时间复杂度和空间复杂度,进一步提高程序设计水平。

5.初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能。

1.2课程设计内容
本课程设计的任务是写一个程序模拟这种情况。

每个队伍都允许插队。

如果你在排队,有一个以上的朋友要求插队,则你可以安排他
们的次序。

每次一个人入队,并且如果这个入队的人发现队伍中有自己的朋友,则可以插入到这个朋友的后面;当队伍中的朋友不止一个的时候,这个人会排在最后一个朋友的后面;如果队伍中没有朋友,则他只能够排在这个队伍的最后面。

每一个入队的人都先进行上述的判断。

当队伍前面的人买到车票之后,依次出队。

系统需求分析
2.1 主体功能
程序从“input.txt”文件读入测试用例,一个文件可包含多个测试用例。

每个用例的第一行是朋友组的数目n(1<=n<=1000)。

对于一个朋友组以朋友的数目j(1<=j<=1000)开始,由朋友的个数以及他们的名字组成,一个空格后接该组朋友的名字,以空格分开,并且每个人的名字都不同。

每个名字不超过四个字母,由{A,B,...,Z,a,b,...,z}组成。

一个朋友组最多有1000个人,每个人只属于一个朋友组。

n=0时,测试数据结束。

下面是一些具体命令:.ENQUEUE——X入队;.DEQUEUE——排队头的人买票,离开队伍,即出队;.STOP——一个测试用例结束。

测试结果输出到“output.txt”文件中。

每个测试用例第一行输出“Scenario#k”,k是测试用例的序号(从1开始)。

对每一个出队命令,输出刚买票离开队伍的人名。

两个测试试用例之间隔一空行,最后一个用例结束不输出空行。

系统概要设计
3.1 系统流程图系统详细设计
本题目主要解决两个问题:一是怎么存放和查找大量数据(主要是姓名);二是怎么操作“ENQUEUE”和“DEQUEUE”命令。

用散列表来存放和查找数据。

由于最多有1000个朋友组,每组最多有1000人,使用平方探测法解决冲突,则表的大小是2*(1000*1000),所以选择TableSize=2000003(2000003是大于2000000的最小素数)。

同一个组内的都是朋友,所以每个人除了记录他的名字name,还要记录他属于哪个组group,另外用info来表示该单元是否被占用,数据结构如图4.1所示。

散列函数是根据Honer法则计算一个以64为阶的多项式,如图4.2所示。

冲突解决方法采用平方探测法,如图4.3所示。

#define TabSize 2000003 typedef struct hashtab *PtrToHash;struct hashtab
/*散列表数据结构*/ { char name[5];
/*名字*/ int group;
/*属于哪个朋友组*/ char info;
/*标志位,该单元是否被占用*/ };图4.1数据结构:散列表
Int Hash(char *key,int TableSize){
Int HashVal=0;
While(key!=NULL)
HashVal=(HashVal<<6)+*key;
Return HashVal%T ableSize;} 图4.2散列函数
Long int Find(PtrT oHash hash,char *c){
key=c;
CurrentPos=Hash(key,TableSize);
CollisionNum=0;
While((单元被占用)and(单元内的名字与查找的名字不同))
{
CurrentPos+=2*(++CollisionNum)-1;
If(CurrentPos>=TabSize)
CurrentPos=TabSize;
}
Return CurrentPos;} 图4.3用平方探测法解决冲突
第二个问题是关于怎么操作“ENQUEUE”和“DEQUEUE”命令。

这可以用队列来模拟。

由于有插队现象的存在,不能单纯的用一个数组来表示队列,因为这样的话,插入一个朋友,则他后面的人都要往后移一个单位,删除一个人,则他后面的人都要前移一个,会降低效率。

所以,采用一个Index标记来表示当前元素的后继元素,最后一个单元的后继元素是第0个,形成环,数据结构如图4.4所示。

不用链表是因为链表存放指针也需要空间,并且链表插入、删除的效率没有数组高。

typedef struct Que *PtrToQue;struct Que
/*队列数据结构*/ { long int HashVal;
/*散列值*/ long int Index;
/*在中的队列序号*/ };图4.4数据结构:队列
输入ENQUEUE命令,如果队伍里有朋友,则排在朋友后面;如果没有朋友,则排在队尾。

入队时,用一个数组记录每个朋友组的最后一位,以便下一个朋友到来时排到他后面,这个数组被称为“插队数组”。

输入DEQUEUE命令,则根据“先进先出”,按照各个元素和它后继元素的先后顺序,每次删除队列重的第一个。

程序结构如图4.5所示。

While(读测试文件){
if(输入”ENQUEUE”)
{
读入名字;
插入散列表;
插入队列;
}
else if(输入”DEQUEUE”)
{
删除队列第一个名字;
将该名字输出到文件;
}
else stop;} 图4.5入队、出队操作测试
5.1 测试方案按输入要求输入正常测试数据,测试程序是否能正确解决问题,得到正确答案。

应注意边界测试。

例如,将n,j分别取为1的用例和n为1000的用例。

n,j比较大时需写程序生成测试用例。

不按输入要求输入数据,测试程序能否对输入内容进行数据合法性检测并进行相应的异常处理。

例如,将n或j取为小于1或大于1000
的数,名字超过4个字母等情况下的测试用例。

5.2 测试结果小结在前面的学习过程中我们学到了很多知识而这次课程设计又是对我们所学的一次总结,刚开始,可以说是没有头绪,于是就去图书馆找资料,找到了一些关于程序方面的,可这远远不够,这只是小小的开始。

我们必须掌握很多已学的知识才能很好的完成本次的课程设计。

在这次课程设计中,总的感觉是我遇到了很多困难这主要是由于我编写代码的经验不足,有时虽然是一个很小的问题但解决起来却花费了我不少的时间,值得欣慰的是,当自己苦思冥想或者和其它同学一起探讨把问题解决的时候我还是觉得获益非浅,这就是在摸索中寻求到的知识。

在设计时也免不了存在着些不足,所以在今后的学习中我会努力取得更大的进步。

虽然对着电脑做程序,有些累,可当看到劳动成果时,却有另一番滋味。

参考文献
[1]范策,周世平,胡晓琨.《算法与数据结构(C语言版)》[M].北京:机械工业出版社,2004 [2]严蔚敏.《数据结构(C语言版)》.北京:清华大学出版社,2004 [3]许卓群,杨冬青,唐世渭,张铭.《数据结构与算法》.北京:高等教育出版社,2004 [4]徐孝凯.《数据结构实用教程(第二版)》.北京:清华大学出版社,2006 附录
附录1 源程序清单
#include #include #include #define T abSize 2000003
/*散列表大小TabSize 是大于表最大空间的素数*/ #define Max 1000001
/*队列空间最大值*/ struct hashtab;typedef struct hashtab *PtrToHash;struct hashtab
/*散列表数据结构*/ { char name[5];
/*名字*/ int group;
/*属于哪个朋友组*/ char info;
/*标志位,该单元是否被占用*/ };struct Que;typedef struct Que *PtrToQue;struct Que
/*队列数据结构*/ { long int HashVal;
/*散列值*/ long int Index;
/*在中的队列序号*/ };
int hashedx=0;
/*标记元素是否已经在散列表里*/ long int Find(PtrToHash hash,char *c)/*查找在散列表中的位置*/ { char *key;long int CurrentPos,CollisionNum;
key=c;for(CurrentPos=0;*key;++key)
/*散列函数,计算散列值*/
CurrentPos=(CurrentPos<<6)+*key;CurrentPos%=TabSize;
/*散列值*/ CollisionNum=0;/*如果当前单元被占用:单元内的元素与当前操作的名字不同,使用平方探测法解决冲突;与当前操作的名字相同,则直接返回在散列中的位置*/ while((hash[CurrentPos].info)&&(strcmp(hash[CurrentPos].name ,c)))
{
/*平方探测法*/
CurrentPos+=2*(++CollisionNum)-1;
if(CurrentPos>=TabSize)
CurrentPos-=TabSize;}
if((hash[CurrentPos].info)&&(strcmp(hash[CurrentPos].name ,c)==0))
/*元素已经在散列表里*/
hashedx=1;else /*元素不在散列表里*/
hashedx=0;return CurrentPos;/*返回在散列表中的位置*/ }
int main(){ long int Find(PtrT oHash hash,char *c);
/*查找在散列表中的位置*/
PtrToHash hash;
/*散列表*/ PtrToQue queue;
/*队列*/ int *grouppos;
/*记录每个朋友组的最后一位,即插队数组*/ int n;
/*测试用例数目*/ int num;
/*当前测试用例序号*/ long int i,ii,j,key,temp;long int head,last;
/*队列的头和尾*/ char c[8],tempc[8];
/*名字*/ FILE *fpin,*fpout;
/*输入、输出文件指针*/
if(!(fpin=fopen(“input.txt”,“r”)))
/*打开测试文件*/ {
printf(“fopen error!”);
/*文件打开错误*/
return-1;} if(!(fpout=fopen(“output.txt”,“w”)))
/*打开输出文件*/ {
printf(“fopen error!”);
return-1;}
hash=(PtrT oHash)malloc(sizeof(struct hashtab)*TabSize);/*为散列表申请空间*/ queue=(PtrToQue)malloc(sizeof(struct Que)*Max);/*为队列申请空间*/ grouppos=(int *)malloc(sizeof(int)*1000);/*申请空间记录每个朋友组的最后一位*/ for(i=0,j=1;i
queue[i].Index=j;queue[i-1].Index=0;/*最后一个单元的后继单元是第0个,形成环*/ num=0;for(fscanf(fpin,“%d”,&n);n;fscanf(fpin,“%d”,&n))/*输入当前测试用例的朋友组数*/ {
if(n<1||n>1000)
/*处理异常输入n*/
{
fprintf(fpout,“n is out of rangen”);
return-1;
}
num++;
if(num!=1)
/*两个测试用例间输入一空行*/ fprintf(fpout,“n”);
for(i=0;i
hash[i++].info=0;
/*初始化散列表,标记位置0*/
for(i=0;i
/*对每一组朋友*/
{
fscanf(fpin,“%d”,&j);
/*当前组里的人数*/
if(j<1||j>1000)
/*处理异常输入j*/
{
fprintf(fpout,“j is out of rangen”); return-1;
}
for(;j;--j)
{
fscanf(fpin,“%s”,c);
/*输入名字*/
for(ii=0;ii
tempc[ii]='';
strcpy(tempc,c);
ii=0;
while(tempc[ii]!='')
/* 是否由四个以内字母组成*/
{
if(tempc[ii]<'A'||('Z''z'||ii>4)
{
fprintf(fpout,“Group %d: Nonstandard namen ”,i);
return-1;
}
ii++;
}
key=Find(hash,c);
/*找到在散列表中的位置*/
if(hashedx==1)/*重名*/
{
fprintf(fpout,“repeated name %sn”,c);
return-1;
}
strcpy(hash[key].name,c);/*插入散列表*/
hash[key].info=1;
/*标记置1,该单元被占用*/
hash[key].group=i;
/*记录他属于哪个组*/
} } for(i=0;i<1000;)
grouppos[i++]=0;/*初始化插队数组*/ head=0;
/*初始化队列头、尾标记*/ last=0;fprintf(fpout,“Scenario #%dn”,num);/*输出当前用例序号到文件*/ for(fscanf(fpin,“%s”,c);;fscanf(fpin,“%s”,c))/*输入命令*/ { if(*c=='E')
/*入队命令*/
{
fscanf(fpin,“%s”,c);
/*输入名字*/
key=Find(hash,c);
/*查找在散列表中的位置*/
if(hashedx==0)/*散列表里没这个人*/ {
fprintf(fpout,“no %sn”,c);
return-1;}
temp=queue[0].Index;
/*队列第0个位置记录队尾的后继单元*/ queue[0].Index=queue[temp].Index;
/*在队列中申请一个新单元,队尾标记后移一个位置*/ queue[temp].HashVal=key;/*入队*/ if(!head)/*如果是队列里的第一个元素*/ last=head=temp;/*队头、队尾标记指向第一个元素*/ if(!grouppos[hash[key].group])/*如果队列里没朋友*/ { queue[temp].Index=0;/*队尾指向对头,形成环*/ queue[last].Index=temp;/*前一次队尾的后继元素是当前元素*/ last=temp;
/*队尾标记指向当前元素*/ grouppos[hash[key].group]=temp;/*插队数组记录该朋友组里已入队的最后一位*/ } else/*如果队列中已经有他的朋友*/ {
queue[temp].Index=queue[grouppos[hash[key].group]].Ind ex;
/*插队到朋友的后面*/
queue[grouppos[hash[key].group]].Index=temp;
/*插队到朋友后面一位的前面*/
grouppos[hash[key].group]=temp;
/*替换插队数组里该组的元素为当前元素*/
if(hash[queue[last].HashVal].group==hash[key].group)
/*如果当前元素和前一元素是朋友,队尾标志指向当前元素*/
last=temp;
}
}
else if(*c=='D')/*出队命令*/
{
if(last==0)
/*不能对空队列执行出队命令*/
{
fprintf(fpout,“Empty queue!nCan't execute DEQUEUE!n”);
return-1;
}
fprintf(fpout,“%sn”,hash[queue[head].HashVal].name);
/*输出队头元素到文件*/
temp=head;
head=queue[temp].Index;
/*队列第一位出队,队头标记后移一位*/
queue[temp].Index=queue[0].Index;
/*队列第0个元素后移一位*/
queue[0].Index=temp;
/*释放空间*/
if(grouppos[hash[queue[temp].HashVal].group]==temp)
/*当前删除的元素是该朋友组在队列里的最后一位*/
grouppos[hash[queue[temp].HashVal].group]=0;
if(last==temp)
/*出队后,队列为空*/
last=0;
}
else
/*输入“STOP”*/
break;
/*测试结束*/
} } fprintf(fpout,“b”);fclose(fpin);fclose(fpout);return 1;}
第四篇:数据结构课程设计报告
正文要求:对每一个题目,正文必须包括以下几个方面知识点回顾:实验要求:
实验过程:包括设计思路,算法描述,程序清单,调试等等;实
验小结:
注意:(1)正文中字体用小四号宋体,行间距1.25倍行距;
(2)页码居中;
(3)A4纸双面打印,在纸的左侧装订。

(4)上交的课程设计报告控制在10页以内。

齐鲁工业大学
理学院
信计11-1
郑桥
一、提示:对于单窗口的服务系统知识点回顾如下:
1、什么是负指数分布?
又称指数分布。

泊松事件流的等待时间(相继两次出现之间的间隔)服从指数分布。

用于描述非老化性元件的寿命(元件不老化,仅由于突然故障而毁坏)。

常假定排队系统中服务器的服务时间和Petri 网中变迁的实施速率符合指数分布。

2、用C语言如何产生随机序列?double rd_MN1(double m,double n){ double r;if(m>n){r=n;n=m;m=r;};r =((double)rand()/((double)(RAND_MAX)+(double)(1)));r = m+ r*(n-m);return r;}
3、用C语言如何产生负指数分布的时间序列?double expntl(double x){ double z;do { z =((double)rand()/ RAND_MAX);} while((z == 0)||(z == 1));return(-x * log(z));//z相当于1-x,而x相当于1/lamda。

} 其中的x相当于1/λ
4、排队论简单叙述;
排队系统主要有:X/Y/Z,其中X表示到达时间间隔的分布,Y表示服务时间的分布,Z表示并列的服务设备的数目。

表示相继到达的时间间隔或服务时间的分布的符号是:
M——负指数分布,D——确定性,Ek——k阶Erlang,GI——相互独立的一般随机分布,G——一般的随机分布。

例如:M/M/1表示达到时间间隔为负指数分布,服务时间为负指。

相关文档
最新文档