约瑟夫环问题说明书.docx
《约瑟夫环问题说明书.docx》由会员分享,可在线阅读,更多相关《约瑟夫环问题说明书.docx(16页珍藏版)》请在冰豆网上搜索。
约瑟夫环问题说明书
---《约瑟夫环》
专业:
自动化
班级:
自动化05
姓名:
陈绍清
学号:
10054112
指导教师:
蔡忠闵刘美兰
2011.12.20
目录
中文摘要3
序言3
1.采用类C语言定义相关数据类型4
2.各模块流程图及伪码算法4
3.函数的调用关系图7
4.调试分析7
a.调试中遇到的问题及对问题的解决方法7
b.算法的时间复杂度和空间复杂度7
5.测试结果8
设计总结10
参考文献11
致谢11
附录:
源程序(带注释)12
中文摘要
本课题约瑟夫环问题是典型的线性表的应用实例,其开发主要包括后台数据库的建立和维护以及前端应用程序的开发两个方面。
对于前者要求建立起数据一致性和完整性强、数据安全性好的库。
而对于后者则要求应用程序功能完备,易使用等特点。
经过分析,我们使用MICROSOFT公司的WIN-TC开发工具,利用其提供的各种面向对象的开发工具,尤其是数据窗口这一能方便而简洁操纵数据库的智能化对象,首先在短时间内建立系统应用原型,然后,对初始原型系统进行需求迭代,不断修正和改进,直到形成用户满意的可行系统。
关键词:
单循环链表;c语言;约瑟夫环;
序言
数据结构是研究数据元素之间的逻辑关系的一门课程,以及数据元素及其关系在计算机中的存储表示和对这些数据所施加的运算。
该课程设计的目的是通过课程设计的综合训练,培养分析和编程等实际动手能力,系统掌握数据结构这门课程的主要内容。
本次课程设计的内容是用单循环链表模拟约瑟夫环问题,循环链表是一种首尾相接链表,其特点是无须增加存储容量,仅对表的链接方式稍作改变,使表处理更加灵活,约瑟夫环问题就是用单循环链表处理的一个实际应用。
通过这个设计实例,了解单链表和单循环链表的相同与不同之处,进一步加深对链表结构类型及链表操作的理解。
通过该课程设计,能运用所学知识,能上机解决一些实际问题,了解并初步掌握设计、实现较大程序的完整过程,包括系统分析、编码设计、系统集成、以及调试分析,熟练掌握数据结构的选择、设计、实现以及操作方法,为进一步的应用开发打好基础。
【实验内容】
约瑟夫(Joseph)问题的一种描述是:
编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。
开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
试设计一个程序求出出列顺序。
【实验目的】
掌握链表的基本操作:
插入、删除、查找等运算,能够灵活应用链表这种数据结构。
【实验要求】
利用单向循环链表存储结构模拟此过程,按照出列的顺序印出各人的编号。
1.采用类c语言定义相关的数据类型
1.1结点的定义
typedefstructNode
{
intdata;
intpassword;
structNode*next;
}Node,*LinkList;
1.2单向循环链表的抽象数据类型定义为:
ADTList﹛
数据对象:
D=﹛ai|ai∈正整数,I=1,2,……,n,n≥0}
数据关系:
R1=﹛|,ai-1,ai∈D,I=1,2,……,n}
基本操作:
CreatLinkList(LinkList*)
操作结果:
构造一个空的线性表L。
ListInsert(&L,i,e)
初始条件:
线性表L已存在,1≤i≤ListLength(L)+1.
操作结果:
在L中第i个位置之前插入新的数据无素e,L长度加1。
ListDelete(&L,i,&e)
初始条件:
线性表L存在非空,1≤i≤ListLength(L).
操作结果:
删除L的第i个元素,并用e返回其值,L长度减1。
2.各模块的流程图及伪码算法
2.1各模块伪码:
(1)主函数:
intmain(void)
{
LinkListL;
intpersonNumber,reportValue;
intarray[MAXPERSONNUMBER];
personNumber=GetPersonNumber();
reportValue=GetFirstCountValue();
CreatLinkList(&L);
InitLinkList(&L,personNumber);
GetOutputOrder(&L,personNumber,reportValue,array);
printResult(array,personNumber);
system("pause");return0;}
(2)链表:
voidCreatLinkList(LinkList*L)
{
(*L)=(LinkList)malloc(sizeof(Node));
if((*L)==NULL)
{
printf("memoryallocationfailed,goodbye");
exit
(1);}}
voidInitLinkList(LinkList*L,intpersonNumber)
{
Node*p,*q;
inti,a;
p=(*L);
p->data=1;
printf("\na=");scanf("%d",&a);
switch(a)
{case1:
p->password=GetPassword1();break;
case2:
p->password=GetPassword2();break;
}
for(i=2;i<=personNumber;i++)
{
q=(LinkList)malloc(sizeof(Node));
if(q==NULL)
{
printf("memoryallocationfailed,goodbye");
exit
(1);}
switch(a){
case1:
p->password=GetPassword1();break;
case2:
p->password=GetPassword2();break;}
q->data=i;
p->next=q;
p=q;
}p->next=(*L);}
(3)输入密码:
intGetPassword1()
{
intpassword1;
staticintcount1=1;
printf("pleaseenterthepasswordof%d:
",count1);
scanf("%d",&password1);
if(password1>MAXPASSWORD||password1<0)
{
printf("yournumberisnotuseful,pleaseprintftheintfrom0to%d:
",MAXPASSWORD);
scanf("%d",&password1);
}
count1++;
returnpassword1;
}
intGetPassword2()
{intpassword2;
staticintcount2=1;
password2=count2+2;
printf("The%dpeople'spasswordis%d\n",count2,password2);
count2++;
returnpassword2;
}
(4)输出结果:
voidprintResult(intarray[],intpersonNumber)
{
inti;
printf("\ntheorderofoutingthequeue:
");
for(i=0;i{
printf("%-3d",array[i]);
}
printf("\n");}
2.2流程图:
(1)
(2)
3.函数的调用关系图
4调试分析:
这是一个使用循环链表的经典问题。
因为要不断地出列,采用链表的存储形式能更好地模拟出列的情况。
问题描述采用不带头结点的循环单链表。
其中,Maxpersonnumber为最大人数值,Maxfirstcountvalue为最大上限数,Maxpassword为最大个人密码值,Next为指向下一个结点的指针。
首先输入人数个数,再输入上限值。
输入a=1,继续输入每个人的密码,再输出(即手动输入密码)。
输入a=2时,系统根据函数intGetPassword2()自动输出每个人的密码和出列顺序。
如果输入的人数超过100或输入的上限值超过30都回出现错误。
5.测试结果:
1、请输入围坐在圆桌周围的人数n:
7
请输入开始上限数m:
20
请依次输入每个人的密码:
3456789
出列的顺序如下:
6217543
2、请输入围坐在圆桌周围的人数n:
5
请输入开始上限数m:
30
请依次输入每个人的密码:
34567
出列的顺序如下:
54132
3、请输入围坐在圆桌周围的人数n:
200
因为输入的人数超过定义的人数,所以出现错误
4、请输入围坐在圆桌周围的人数n:
9
请输入开始上限数m:
50
因为输入的上限数超过定义的上限数,所以出现输出错误
5、请输入围坐在圆桌周围的人数n:
8
请输入开始上限数m:
14
请依次输入每个人的密码:
345678910
出列的顺序如下:
68154732
设计总结
我的这次数据结构课程设计的题目是:
《约瑟夫环》,通过对该题目的设计,我加深了对数据结构及存储结构的理解,进一步地理解和掌握了课本中所学的各种数据结构,尤其是对单循环链表上基本运算的实现,学会了如何把学到的知识用于解决实际问题,锻炼了自己动手的能力。
在此过程我深深地意识到自己知识的严重不足!
不断地充实自己才是目前的当务之急!
三周的课程设计很短暂,但其间的内容是很充实的,在其中我学习到了很多平时书本中无法学到的东西,积累了经验,锻炼了自己分析问题,解决问题的能力,并学会了如何将所学的各课知识融会,组织起来进行学习,总而言之这三周中我学到很多,收益匪浅同时一定程度上提高了自己程序设计和阅读程序的能力。
本次课程设计提高了我们的专业知识,使自己所学的内容运用到实际中来,也增强了实际操作能力,为以后的工作学习提供了一个良好的铺垫。
通过本次课程设计的实践学习,我认识到了学好计算机要重视实践操作,所以在以后的学习过程中,我会更加注重实践操作,使自己更好地学好计算机。
参考文献
1严蔚敏,吴伟民.《数据结构(C语言版)》.清华大学出版社.
2严蔚敏,吴伟民.《数据结构题集(C语言版)》.清华大学出版社.
3谭浩强.《c语言程序设计》.清华大学出版社.
4.李春葆编著 《数据结构教程(上机实验指导)》 清华大学出版社
5.叶核亚主编 《数据结构(C++版)》 机械工业出版社
致谢
课程设计完成之际,除了感到一种轻松以外,马上想到的就是对老师以及在课程设计过程中帮助我的同学们,因为他们的指导和鞭策,才使我下定决心,集中精力投入到课程设计的建设。
首先感谢我的指导老师刘美兰老师,他在我的课程设计过程中提出了指导性的方案和架构,比如让我把密码设计成自动和手动两种方式,使我在不熟悉的领域中仍能迅速掌握新的技术。
感谢我的数据结构老师蔡忠闵老师在以往的基础课学习中为我打下良好的基础,这是我这次课程设计能够顺利完成的前提。
我的同学在这次课设中也给予了我一些好的建议!
在此,也谢谢他们!
附件一.源程序:
#include"stdio.h"
#include"stdlib.h"
/*宏定义*/
#defineMAXPERSONNUMBER100
#defineMAXFIRSTCOUNTVALUE30
#defineMAXPASSWORD400
/*结构体的定义*/
typedefstructNode
{
intdata;
intpassword;
structNode*next;
}Node,*LinkList;
/*函数的声明*/
voidCreatLinkList(LinkList*);
voidInitLinkList(LinkList*,int);
intGetPassword1();
intGetPassword2();
intGetPersonNumber();
intGetFirstCountValue();
voidGetOutOrder(LinkList*,int,int,int*);
voidprintResult(int*,int);
/*构建单链表*/
voidCreatLinkList(LinkList*L)
{
(*L)=(LinkList)malloc(sizeof(Node));
if((*L)==NULL)
{
printf("memoryallocationfailed,goodbye");
exit
(1);
}
}
/*初始化单链表*/
voidInitLinkList(LinkList*L,intpersonNumber)
{
Node*p,*q;
inti,a;
p=(*L);
p->data=1;
printf("\na=");
scanf("%d",&a);
switch(a)
{case1:
p->password=GetPassword1();break;
case2:
p->password=GetPassword2();break;
}
for(i=2;i<=personNumber;i++)
{
q=(LinkList)malloc(sizeof(Node));
if(q==NULL)
{
printf("memoryallocationfailed,goodbye");
exit
(1);
}
switch(a)
{case1:
p->password=GetPassword1();break;
case2:
p->password=GetPassword2();break;
}
q->data=i;
p->next=q;
p=q;
}
p->next=(*L);
}
/*给每个人赋秘密*/
intGetPassword1()
{
intpassword1;
staticintcount1=1;
printf("pleaseenterthepasswordof%d:
",count1);
scanf("%d",&password1);
if(password1>MAXPASSWORD||password1<0)
{
printf("yournumberisnotuseful,pleaseprintftheintfrom0to%d:
",MAXPASSWORD);
scanf("%d",&password1);
}
count1++;
returnpassword1;
}
intGetPassword2()
{intpassword2;
staticintcount2=1;
password2=count2+2;
printf("The%dpeople'spasswordis%d\n",count2,password2);
count2++;
returnpassword2;
}
/*确定需要处理的人数*/
intGetPersonNumber()
{
intpersonNumber;
printf("pleaseenterthepersonnumber:
");
scanf("%d",&personNumber);
while(personNumber>MAXPERSONNUMBER||personNumber<0)
{
printf("\nyournumberisnotuseful,pleaseprintftheintfrom0to%d",MAXPERSONNUMBER);
scanf("%d",&personNumber);
}
printf("thefinalpersonnumberis%d\n",personNumber);
returnpersonNumber;
}
/*确定开始的上限值*/
intGetFirstCountValue()
{
intfirstCountValue;
printf("pleaseentertheinitialgetfirstcountvalue:
");
scanf("%d",&firstCountValue);
while(firstCountValue>MAXFIRSTCOUNTVALUE||firstCountValue<0)
{
printf("\nyournumberisnotuseful,pleaseprintftheintfrom0to%d;",MAXFIRSTCOUNTVALUE);
scanf("%d",&firstCountValue);
}
printf("thefinalfirstcountvalueis%d",firstCountValue);
returnfirstCountValue;
}
/*得到真确的顺序*/
voidGetOutOrder(LinkList*L,intpersonNumber,intreportValue,intarray[MAXPERSONNUMBER])
{
Node*p,*q;
intcount=1,i=0;
p=(*L);
while(personNumber)
{
while(count!
=reportValue)
{
q=p;
p=p->next;
count++;
}
array[i++]=p->data;
reportValue=p->password;
q->next=p->next;
free(p);
p=q->next;
count=1;
personNumber--;
}
}
voidprintResult(intarray[],intpersonNumber)/*输出结果*/
{
inti;
printf("\ntheorderofoutingthequeue:
");
for(i=0;i{
printf("%-3d",array[i]);
}
printf("\n");
}
/*主函数的实现*/
intmain(void)
{
LinkListL;
intpersonNumber,reportValue;
intarray[MAXPERSONNUMBER];
personNumber=GetPersonNumber();
reportValue=GetFirstCountValue();
CreatLinkList(&L);
InitLinkList(&L,personNumber);
GetOutOrder(&L,personNumber,reportValue,array);
printResult(array,personNumber);
system("pause");
return0;
}