武汉理工大学数据结构课设约瑟夫环.docx
- 文档编号:29217770
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:20
- 大小:182.26KB
武汉理工大学数据结构课设约瑟夫环.docx
《武汉理工大学数据结构课设约瑟夫环.docx》由会员分享,可在线阅读,更多相关《武汉理工大学数据结构课设约瑟夫环.docx(20页珍藏版)》请在冰豆网上搜索。
武汉理工大学数据结构课设约瑟夫环
附件1:
学号:
012111034*****
课程设计
题目
数据结构
学院
计算机科学与技术学院
专业
计算机科学与技术学院
班级
姓名
指导教师
2013
年
6
月
1
日
目录
一.需求分析3
1.1问题描述3
1.2功能分析3
二.概要设计4
2.1循环链表抽象数据类型定义4
2.2本程序包含一下几个模块4
(1)构造结点模块4
(2)创建链表模块4
(3)出队处理模块4
(4)约瑟夫环说明输出模块4
(5)菜单模块5
(6)主函数模块5
三、详细设计6
3.1主函数6
3.2链表的创建8
3.3出队处理8
3.4约瑟夫环说明模块9
3.5菜单模块9
四、程序调试与测试10
五.设计总结13
一.需求分析
1.1问题描述
约瑟夫环问题描述的是:
设编号为1,2,…,n的n(n>0)个人按顺时针方向围坐一圈,每个人持有一正整数密码。
开始时选择一个正整数作为报数上限m,从第一个人开始顺时针方向自1起顺序报数,报到m时停止报数,报m的人出圈,将他的密码作为新的m值,从他在顺时针方向上的下一个人起重新从1报数。
如此下去,直到所有人都出圈为止。
令n最大值为100。
要求设计一个程序模拟此过程,求出出圈的编号序列。
如下图分析:
1.2功能分析
为了讨论方便,先把问题稍微改变一下,并不影响原意:
问题描述:
n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。
求胜利者的编号。
我们知道第一个人(编号一定是m%n-1)出列之后,剩下的n-1个人组成了一个新的约瑟夫环(以编号为k=m%n的人开始):
kk+1k+2...n-2,n-1,0,1,2,...k-2并且从k开始报0。
现在我们把他们的编号做一下转换:
k-->0
k+1-->1
k+2-->2
...
...
k-2-->n-2
变换后就完完全全成为了(n-1)个人报数的子问题,假如我们知道这个子问题的解:
例如x是最终的胜利者,那么根据上面这个表把这个x变回去不刚好就是n个人情况的解吗?
变回去的公式很简单:
x'=(x+k)%n
如何知道(n-1)个人报数的问题的解?
显然,只要知道(n-2)个人的解就行了。
(n-2)个人的解呢?
当然是先求(n-3)的情况----这显然就是一个倒推问题!
题。
二.概要设计
2.1循环链表抽象数据类型定义
typedefstructLNode//定义单循环链表中节点的结构
{
intnum;//编号
intpas;//password
structLNode*next;//指向下一结点的指针
}LNode;
2.2本程序包含一下几个模块
(1)构造结点模块
LNode*createNode(intm_num,intm_pwd)
{
LNode*p;
p=(LNode*)malloc(sizeof(LNode));//生成一个结点
p->num=m_num;//把实参赋给相应的数据域
p->pas=m_pas;
p->next=NULL;//指针域为空
returnp;
}
(2)创建链表模块
voidcreateList(LNode*L,intn)
(3)出队处理模块
voidjose(LNode*L,intm_pas)
(4)约瑟夫环说明输出模块
voidinstruction()
(5)菜单模块
voidmenu()
(6)主函数模块
intmain()
三、详细设计
3.1主函数
根据流程图,主函数程序如下:
intmain()
{
intn,m,x;
LNode*ppHead=NULL;
menu();
for(;;){
printf("\n请选择要执行的操作:
");
scanf("%d",&x);
system("cls");
switch(x){
case1:
printf("****************************************************************\n");
printf("约瑟夫环:
\n");
printf("编号为1,2,3,4…,n的n个人按顺时针方向围坐一圈,每人持有一个密\n");
printf("码(正整数).一开始任选一个正整数作为报数的上限值m,从第一个人开始\n");
printf("按顺时针方向自1开始顺序报数,报到m时停止.报m的人出列,将他的密码\n");
printf("m作为新的m值,从他在顺时针方向上的下一人开始重新从1报数,如此下去,\n");
printf("直到所有人全部出列为止.编程打印出列顺序.\n");
printf("****************************************************************\n");
main();
break;
case2:
printf("\n请输入总人数n:
");
scanf("%d",&n);
printf("请输入开始上限数m:
");
scanf("%d",&m);
createList(&ppHead,n);
printf("\n");
printf("出队顺序:
\n");
jose(ppHead,m);
printf("\n约瑟夫环游戏结束!
\n");
main();
break;
case3:
exit(0);
default:
system("cls");
printf("\n您选择的操作有误,请重新选择...\n\n\n");
main();
}
}
return0;
}
3.2链表的创建
创建链表函数程序如下:
voidcreateList(LNode**L,intn)
{
inti,m_pas;
LNode*p,*cur;//cur:
浮标指针
for(i=1;i<=n;i++)
{
printf("输入第%d个人的密码:
",i);
scanf("%d",&m_pas);//输入持有密码
p=createNode(i,m_pas);//调用构造结点函数
if(*L==NULL)//如果头结点为空
{
*L=cur=p;//生成头结点,让cur指向他
cur->next=*L;//cur的指针域指向自身
}
else//如果不为空,则插入结点
{
p->next=cur->next;
cur->next=p;
cur=p;//cur指向新插入结点
}
}
printf("完成创建!
\n");//提示链表创建完成
}
3.3出队处理
出队函数程序如下:
voidPop(LNode*L,intm_pas)
{
inti,j;
LNode*p,*p_del;//定义指针变量
for(i=1;p!
=L;i++){
for(j=1;j p=L;//p赋值为L,p指向要删除结点的前一个结点 L=L->next;//L指向下一个元素 } p->next=L->next;//p结点与头结点链接 i=L->pas;//i赋值为L->pas j=L->num;//j赋值为L->num,j为要删除的密码值 printf("第%d个人出列,密码: %d\n",j,i); m_pas=L->pas;// free(L);//释放头结点 L=p->next; } i=L->pas; j=L->num; printf("最后一个出列是%d号,密码是: %d\n",j,i); free(L);//释放头结点 } 3.4约瑟夫环说明模块 voidinstruction() { printf("****************************************************************\n"); printf("约瑟夫环: \n"); printf("编号为1,2,3,4…,n的n个人按顺时针方向围坐一圈,每人持有一个密\n"); printf("码(正整数).一开始任选一个正整数作为报数的上限值m,从第一个人开始\n"); printf("按顺时针方向自1开始顺序报数,报到时停止.报m的人出列,将他的密码\n"); printf("m作为新的m值,从他在顺时针方向上的下一人开始重新从1报数,如此下去,\n"); printf("直到所有人全部出列为止.编程打印出列顺序.\n"); printf("******************************************************\n"); return0; } 3.5菜单模块 voidmenu(){ printf("**************************约瑟夫环*****************************\n"); printf("\n"); printf("*1.输入约瑟夫环数据*\n"); printf("*2.什么是约瑟夫环*\n"); Printf("*3.退出系统*n"); printf("******************************************************\n"); } 四、程序调试与测试 1.调用模块时,结点结构的调用与其他模块产生冲突,导致每一行都出现两次错误,加入子函数的声明后错误消失。 2.刚开始时曾忽略了一些变量参数的标识"&"和“*”,使调试程序时费时不少。 今后应重视确定参数的变量和赋值属性的区分和标识。 3.本次课程设计采用数据抽象的程序设计方法,将程序划分为三个层次结构: 元素节点、单向循环链表,主控制模块。 思路较为清晰,实现调用顺利。 经过本次实验,使我对数据结构这门课程有了进一步的了解,每一个程序经过需求分析、概要设计、详细设计之后,思路即清晰呈现,程序也很快就出来了,最后经过调试、运行又有新的体验。 <测试用例> 本程序开始运行界面如下: 图1开始界面 选择1进入约瑟夫环问题阐述。 图2约瑟夫环问题阐述 ①选择2,输入下列数据测试: 请输入总人数n: 7 请输入开始上限数m: 20; 请依次输入每个人的密码: 3172484 出队顺序: 6147235 ②继续选择2,输入下列数据测试: 请输入总人数n: 5 请输入开始上限数m: 30 请依次输入每个人的密码: 34567 出队顺序: 53124 测试完成,选择0退出。 五.设计总结 我的课设题目是约瑟夫循环。 这次的课程设计让我受益匪浅,让我明白了许多以前不了解或者是明白的事情,也让我懂得了实践出真知,无论理论学习的多么好,但是没有一个实践的话,一切都是空谈,以前我总是以为我会编写,会运用语言写出我想要的东西,但是一动手才知道,一切都是空谈,我不知道如何下手,如后完成这个问题,还是前后参考了很多文献,前人的程序才对自己的实验有了点想法,所以以后不能再好高骛远,要脚踏实地,努力的完成自己的学业。 本次课设,也让我明白了团队合作的重要性,在我做课设的时间里,同学们给予了我很大的帮助,帮我解决了很多问题,一个人的力量毕竟是有限,所以我们要学会合作,学会交流,这是我们生存的一项技能。 附件1 #include #include #include #include typedefstructLNode//定义单循环链表中节点的结构 { intnum;//编号 intpas;//password structLNode*next;//指向下一结点的指针 }LNode; voidmenu(){ printf("制作人: 万全旦\n"); printf("学号: 0121110340621\n"); printf("**************************约瑟夫环*****************************\n"); printf("\n"); printf("*1.输入约瑟夫环数据*\n"); printf("*2.什么是约瑟夫环*\n"); printf("*3.退出系统*\n"); printf("******************************************************\n"); } LNode*createNode(intm_num,intm_pas) { LNode*p; p=(LNode*)malloc(sizeof(LNode));//生成一个结点 p->num=m_num;//把实参赋给相应的数据域 p->pas=m_pas; p->next=NULL;//指针域为空 returnp; } voidcreateList(LNode*L,intn) { inti,m_pas; LNode*p,*cur;//cur: 浮标指针 for(i=1;i<=n;i++) { printf("输入第%d个人的密码: ",i); scanf("%d",&m_pas);//输入持有密码 p=createNode(i,m_pas);//调用构造结点函数 if(L==NULL)//如果头结点为空 { L=cur=p;//生成头结点,让cur指向他 cur->next=L;//cur的指针域指向自身 } else//如果不为空,则插入结点 { p->next=cur->next; cur->next=p; cur=p;//cur指向新插入结点 } } printf("完成创建! \n");//提示链表创建完成 } voidPop(LNode*L,intm_pas) { inti,j; LNode*p;//*p_del;//定义指针变量 for(i=1;p! =L;i++){ for(j=1;j p=L;//p赋值为L,p指向要删除结点的前一个结点 L=L->next;//L指向下一个元素 } p->next=L->next;//p结点与头结点链接 i=L->pas;//i赋值为L->pas j=L->num;//j赋值为L->num,j为要删除的密码值 printf("第%d个人出列,密码: %d\n",j,i); m_pas=L->pas;// free(L);//释放头结点 L=p->next; } i=L->pas; j=L->num; printf("最后一个出列是%d号,密码是: %d\n",j,i); free(L);//释放头结点 } voidinstruction() { printf("****************************************************************\n"); printf("约瑟夫环: \n"); printf("编号为1,2,3,4…,n的n个人按顺时针方向围坐一圈,每人持有一个密\n"); printf("码(正整数).一开始任选一个正整数作为报数的上限值m,从第一个人开始\n"); printf("按顺时针方向自1开始顺序报数,报到时停止.报m的人出列,将他的密码\n"); printf("m作为新的m值,从他在顺时针方向上的下一人开始重新从1报数,如此下去,\n"); printf("直到所有人全部出列为止.编程打印出列顺序.\n"); printf("******************************************************\n"); } intmain() { intn,m,x; LNode*L=NULL; menu(); for(;;){ printf("请选择要执行的操作: \n"); scanf("%d",&x); system("cls"); switch(x){ case1: printf("****************************************************************\n"); printf("约瑟夫环: \n"); printf("编号为1,2,3,4…,n的n个人按顺时针方向围坐一圈,每人持有一个密\n"); printf("码(正整数).一开始任选一个正整数作为报数的上限值m,从第一个人开始\n"); printf("按顺时针方向自1开始顺序报数,报到m时停止.报m的人出列,将他的密码\n"); printf("m作为新的m值,从他在顺时针方向上的下一人开始重新从1报数,如此下去,\n"); printf("直到所有人全部出列为止.编程打印出列顺序.\n"); printf("****************************************************************\n"); main(); break; case2: printf("\n请输入总人数n: "); scanf("%d",&n); printf("请输入开始上限数m: "); scanf("%d",&m); createList(L,n); printf("\n"); printf("出队顺序: \n"); Pop(L,m); printf("\n约瑟夫环游戏结束! \n"); main(); break; case3: exit(0); default: system("cls"); printf("\n您选择的操作有误,请重新选择...\n\n\n"); main(); } } return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 武汉理工大学 数据结构 约瑟夫