计1143班 刘镇 58504337约瑟夫环游戏课程设计文档.docx
《计1143班 刘镇 58504337约瑟夫环游戏课程设计文档.docx》由会员分享,可在线阅读,更多相关《计1143班 刘镇 58504337约瑟夫环游戏课程设计文档.docx(16页珍藏版)》请在冰豆网上搜索。
计1143班刘镇58504337约瑟夫环游戏课程设计文档
烟台大学计算机学院
数据结构课程设计
题目:
约瑟夫环游戏
班级:
计算机114-3班
姓名:
刘镇
学号:
201158504337
日期:
2013年6月1日
导师:
范宝德老师
地点:
钟楼4309
目录
一、需求分析3
1.1题目描述:
3
1.2题目分析:
3
1.3平台语言及数据结构:
3
二、概要分析3
2.1欢迎welcome():
3
2.2主界面mainmenu():
4
2.3创建循环列表create():
4
2.4查找search():
4
2.5输出序列linkout():
5
2.6结构体设计:
5
三、程序设计主流程5
3.1总体设计:
5
3.2详细流程图6
四、详细设计7
4.1link.h:
7
4.2link.cpp:
7
五、调试与测试10
5.1调试:
10
5.2测试:
13
六、存在问题与体会:
14
6.1问题总结:
14
6.2心得体会:
14
一、需求分析
1.1题目描述:
约瑟夫环问题描述:
编号为1,2,…,n的n个人按顺时针方向坐一圈,每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上相值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他的顺时针方向上的下一个人开始重新从1报数,如此下去,直至所有人全部出列为止。
设计一个程序求出出列顺序。
1.2题目分析:
约瑟夫环问题主要是涉及到数据结构中的循环单链表的内容,通过插入链表,查询链表实现序列输出。
开始主界面通过分支选择实现;主要的问题分为两个大部分,其一、是对循环单链表的创建,由于涉及到结构体和指针,因此可以通过将结构体与函数单独封装在头文件中,只有引用头文件即可,结构体内是基本的链表结构;其二、是搜索算法的涉及,思路是按照问题描述中:
按初始密码查找标号修改初始密码,打印结果,改变链表结构再次搜查,直到链表内容清空为止结束搜索。
其中剔除当前查找目标并将指针转到下一目标可通过将下一目标的密码及编号完全复制,删除下一目标,修改当前目标的指针实现。
1.3平台语言及数据结构:
使用C++语言设计,windows系统,数据结构:
单向循环链表
二、概要分析
2.1欢迎welcome():
基本的欢迎界面打印。
2.2主界面mainmenu():
打印选择框图,并通过输入choice以switch-case语句实现功能选择,直接调用linkout(),实现序列输出。
2.3创建循环列表create():
定义结构体(在2.6中详细说明)指针head、link、me,
head=NULL创建一个没有头结点的单向循环链表,并采for(i=1;i<=n;i++)
自动生成新的链表存储空间me=(Linklist)malloc(sizeof(Node)),通过用户输入获取当前循环编号密码,编号自动生成,暂存在me指向的空间,最后编号及密码存入link指针指向空间中;当前指针link后移,并释放me的值。
直到link->head时创建单向循环链表成功,并返回head的值。
单项循环链表示意图:
2.4查找search():
形式参数传入Linklist链表L,初始密码initialcode,及总人数num,在已经构建成的链表L中,以for(inti=1;i<=num;i++)控制人数循环,for(intj=1;j如此循环下去,直到最后变为空的单循环链表为止。
2.5输出序列linkout():
声明变量,获取总人数,调用create(),构造链表,输入获取初始密码,调用search(),实现报数和结果序列输出。
2.6结构体设计:
宏定义NULL0;结构体中数据是编号num,密码code,指向下一结点的结构体指针next。
三、程序设计主流程
3.1总体设计:
3.2详细流程图
2
1
N
Y
四、详细设计
Joseph:
4.1link.h:
#defineNULL0
typedefstructNode
{
intnum;//编号
intcode;//密码
structNode*next;
}Node,*Linklist;
voidmainmenu();//主菜单
voidlinkout();//求出序列
Linklistcreate(intn);//创建循环单链表
voidsearch(LinklistL,intinitialcode,intnum);//实现报数
4.2link.cpp:
#include
#include
#include
#include
#include
#include
#include"link.h"
usingnamespacestd;
voidwelcome()//欢迎界面
{
cout<<"+--------------------------------------+\n";
cout<<"||\n";
cout<<"|欢迎尝试约瑟夫环游戏|\n";
cout<<"||\n";
cout<<"+--------------------------------------+\n";
}
voidmainmenu()//主界面
{
do{
charchoice;
choice=-1;
cout<<"\n";
cout<<"+-----------------------------------------+\n";
cout<<"|开始约瑟夫环请按1退出请按2|\n";
cout<<"+-----------------------------------------+\n";
cout<<"请输入您的选择:
";
cin>>choice;
switch(choice)
{
case'1':
linkout();
break;
case'2':
cout<<"欢迎下次使用!
退出..."<system("pause");
exit(0);
break;
default:
printf("\n无效选项!
");
break;
}
}while(true);
}
Linklistcreate(intn)
{
Linklisthead,link,me;
head=NULL;
for(inti=1;i<=n;i++)
{
if(head==NULL)//链表为空
{
link=(Linklist)malloc(sizeof(Node));//开辟内存
head=link;//link与head指向同一内存空间
}
else//若列表不为空,通过创建开辟内存给新的Node即me
{
me=(Linklist)malloc(sizeof(Node));//为之开辟内存,获成功则返回内存地址给指针me
link->next=me;//将me指向的内存块(Node)连在单链表中
link=me;//将link指针指向me
}
cout<<"请输入第"<
\n";
cin>>link->code;//通过输入获取当前编号下的密码
link->num=i;//将编号放入link中
cout<<"第"<
"<code<}
link->next=head;//link已经在最后,通过link的next指向head构成循环链表
link=head;//link与头指针指向首元素
returnhead;
}
voidsearch(LinklistL,intinitialcode,intnum)//用循环链表实现报数问题
{
Linklisthead,link,me;
head=L;
link=head;
me=(Linklist)malloc(sizeof(Node));
cout<<"出列的顺序为:
";
for(inti=1;i<=num;i++)
{
for(intj=1;j{
link=link->next;//找到用link指向当前编号对应的内存地址
}
initialcode=link->code;//用当前查找的编号的密码更新初始密码
cout<num<<"";//打印查找到的当前编号
/*以下是通过将下一人的编号与密码赋值给link,
将下一人的内存清空,并将并改变指针以实现总体上的循环链表结构
*/
link->num=link->next->num;
link->code=link->next->code;
me=link->next;
link->next=link->next->next;
free(me);
}
cout<<"\n\n";
}
voidlinkout()
{
intinitialcode,num;
LinklistL;
cout<<"输入初始人数:
"<cin>>num;
if(num<=30)
{
L=create(num);
cout<<"输入初始密码:
\n";
cin>>initialcode;
search(L,initialcode,num);
cout<<"\n\n\n";
}
}
intmain()
{
welcome();
mainmenu();
system("pause");
return0;
}
五、调试与测试
5.1调试:
主界面:
打印主界面,用户输入操作选择:
选择1:
输入选项1并输入初始人数,开始键入每一个的编号密码:
输入初始人数(7人),依次键入密码(3,1,7,2,4,8,4):
打印出序列结果:
利用循环返回主界面,若选择2退出:
5.2测试:
Joseph
编号
密码
*next
head
1
3
2号地址
2
1
3号地址
3
7
4号地址
4
2
5号地址
5
4
6号地址
6
8
7号地址
7
4
head
结果预测:
6147235
测试结果:
6147235
操作选项测试:
输入选项
预测结果
测试结果
-9
无效提示
无效提示
0
无效提示
无效提示
1
进入
进入
2
退出
退出
a
无效提示
无效提示
不输入
无效提示
无效提示
六、存在问题与体会:
6.1问题总结:
1、当输入操作选择项是“afsfs”字符串时,会连续打印主界面。
2、在代码的细节有欠缺,当空指针时或是空链表时,未作处理。
6.2心得体会:
本次课程设计,在老师的总体指导下,对项目要求做了细致的分析,课程设计如果想完成,并非难事,而做细致些,做透彻些,做像样些,都不是一蹴而就的,网上资源非常多,我选择的题目“约瑟夫环问题”有很多人做过,但看的很多都有些小毛病,例如在输入数据特定,结果正确,真正多测试几次,会出现错误结果,还有在网上确实也存在不错的模版,不论是大的格式还是具体实现,都能比较清晰的展现出来,这是十分难得的,我也借鉴了比较好的几个方面,例如对于外部界面的书写,以及代码的优化,约瑟夫问题有很多小点可以多解决算法,而唯一相同的都是在单项循环列表的数据结构下操作数据的,因此找到问题的主要是数据结构,问题就集中了,至于具体怎样实现,可以使因人而异;代码中全部属于自己编写,感觉先在书面上做好分析十分有效,以此为例,当对任务细分后,就变成两个小问题,一个是怎样创建一个单向循环链表,一个是怎样在已经存在的链表中实现“报数”查找及输出;单向链表比较容易,一个头指针指示链表总体,一个临时指针用于暂时存放输入的数据,还有一个移动指针随着链表的增长不断移动,以及移动过程中指针变换问题,在单向链表的基础上将末尾的指针指向头,就形成了环结构,就是所说的单向循环链表;至于搜索“报数”就是遍历链表结构,找到数据,提出数据,更新结构直到链表为空结束。
在示例草图中演示结果,有了清晰思路,就可以完成本次任务。