约瑟夫环问题课程设计报告成果.docx

上传人:b****5 文档编号:6113193 上传时间:2023-01-03 格式:DOCX 页数:16 大小:244.27KB
下载 相关 举报
约瑟夫环问题课程设计报告成果.docx_第1页
第1页 / 共16页
约瑟夫环问题课程设计报告成果.docx_第2页
第2页 / 共16页
约瑟夫环问题课程设计报告成果.docx_第3页
第3页 / 共16页
约瑟夫环问题课程设计报告成果.docx_第4页
第4页 / 共16页
约瑟夫环问题课程设计报告成果.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

约瑟夫环问题课程设计报告成果.docx

《约瑟夫环问题课程设计报告成果.docx》由会员分享,可在线阅读,更多相关《约瑟夫环问题课程设计报告成果.docx(16页珍藏版)》请在冰豆网上搜索。

约瑟夫环问题课程设计报告成果.docx

约瑟夫环问题课程设计报告成果

计算机学院网络工程专业

数据结构课程设计

题目:

排序系统设计(约瑟夫环问题)

班级:

网工10101班

姓名:

罗源学号201017030128

同组人姓名:

房鸿朝

起迄日期:

2010年12月26日             

课程设计地点:

E3-A513               

指导教师:

徐晓蓉

完成日期:

2011年12月

评阅意见:

 

成绩评定:

评阅人:

日期:

摘要:

约瑟夫问题是由古罗马著名的史学家Josephus提出的问题演变而来,所以通常称为Josephus问题。

改进约瑟夫问题的描述是:

编号为1,2,…,n的n个人按顺时针方向围坐一圈,每人有一个密码Ki(整数),留作其出圈后应报到Ki后出圈。

报数方法采用顺时针报数和逆时针报数交替进行,初始密码可任意确定。

求最后剩下的人的编号。

这个就是约瑟夫环问题的实际场景,后来老师要求我们对要求中的每人所持有的密码以及第一次的报数上限值要用随机数产生。

因此约瑟夫环问题如果采用双向循环链表则能很好的解决。

循环链表的数据结构,就是将一个链表的尾元素指针指向队首元素。

p->link=head解决问题的核心步骤:

先建立一个具有n个链结点,无头结点的循环链表,然后确定第一个报数人的位置,并不断地从链表中删除链结点,直到链表为空。

……

 

图示

目录

1.需要分析4

1.1功能分析4

1.2设计平台4

2.概要设计5

2.1算法概述5

2.2算法具体分析5

2.3结构体Node6

2.4函数流程图6

3.详细设计与实现8

3.1创建节点Node8

3.2创建单循环链表8

3.3查找并删除节点8

3.4菜单及清屏函数9

4.调试与操作说明9

4.1调试情况9

4.2操作说明10

总结13

致谢14

参考文献14

附录15

第1章.需要分析

1.1功能分析

本次选做的课程设计是改进约瑟夫(Joseph)环问题。

我选择了和房鸿朝两个人来完成本次课程设计的作业。

约瑟夫环问题是一个古老的数学问题,本次课题要求用程序语言的方式解决数学问题。

此问题仅使用单循环链表就可以解决此问题。

问题描述:

编号为1,2…n的n个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。

一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数,报m的人出列,将他的密码作为新的m值,从他的顺时针方向上的下一个开始重新从1报数,如此下去,直至所有人全部出列为止,设计一个程序求出出列顺序。

功能要求:

A利用单循环链表作为存储结构模拟此过程;

B键盘输入总人数、初始报数上限值m及各人密码;

C按照出列顺序输出各人的编号。

1.2设计平台

Windows2000以上操作系统;MicrosoftVisualC++6.0

第2章.概要设计

2.1算法概述

建立一个循环单链表,然后输入要建立结点的个数,在每个结点输入一个密码,同时按输入时的顺序进行编号:

1,2,3,4,……n.任选一个正整数m0作为初始报数上限值.从定义的那个头结点开始,数到m0,输出该结点所储存的编号和密码.并将该密码作为新的m0值,同时还将该密码所在的结点删除.如此循环链表还剩最后一个数据的时候停止此循环.再将最后一个没在循环里面的编号和密码另外输出.循环链表如图1所示:

图1循环单链表的创建

2.2算法具体分析

(1)这几个函数是构建本程序菜单所必须的函数

(2)creat()初始化循环链表,开辟一个空间作为头结点,并让H先让它指向自己,令链表循环起来.利用for循环和s=(Linklist)malloc(sizeof(Node));向循环链表里面插入数据(包括编号和密码)。

(3)search()主要用于解决约瑟夫环问题,首先调用creat()建立的循环链表,定义两个指针prep和p,再定义count作为计数器,此时需要任意输入一个正整数m0作为初始报数上限值,当计数器count=x时就把该指针所指向的数据输出并把该数据赋给x,作为新的报数上限值.然后删除该结点,pre和p的主要作用是在把输出数据之后的结点删除.如此循环,直到还剩最后一个结点.

(4)菜单2选项用于约瑟夫环问题的解析说明,增强使用者对本程序的理解。

2.3结构体Node

主要功能是创建结点,每个结点数值域包括data,cipher,还有指示前驱结点的指针H,和指示后继结点的指针s

2.4函数流程图

2.4.1主函数流程图

 

2.4.1解决约瑟夫环问题相关函数流程图

 

第3章.详细设计与实现

3.1创建节点Node

链表都是由一个个结点组成,由于结点的不同,组成的链表也不同。

由于每一个结点有一个密码和一个序号,所以可以将结点结构体定义为:

(如图3.1)

typedefstructNode

{

intm;//密码

intn;//序号

structNode*next;

}Node,*Linklist;图3.1(节点)

3.2创建单循环链表

创建一个空单循环链表,双向循环链表和每个结点包括两个域:

元素域和指针域。

形成单循环链表的原理:

定义三个指针变量H,r,s,三指针开始全部指向头结点,在插入操作开始后,H不变仍指向头结点,s指针在插入过程中始终指向新插入的节点,而r指针紧随其后,用于将新插入的节点和前一个节点连接起来,最后通过r指向头指针H,来完成环的操作。

关键代码实现如下:

if(H==NULL){H=s,r=H;}//从链表的第一个节点插入

else{r->next=s,r=s;//r后移}//链表的其余节点插入

结束for循环后结成环的操作:

r->next=H;/*生成循环单链表*/

returnH;

3.3查找并删除节点

每当结点计数到某一结点时,将他的前驱结点接到他的后继结点,然后将他的密码值cipher赋给计数变量,再将此结点删除。

如此循环下去,直到最后变为空的单循环链表为止。

函数通过代码:

p=H;pre=p;p=p->next;pre->next=p->next;p=pre->next;

来删除当前的那个结点q,通过循环来一次次删除当前的结点,直到链表中剩下最后一个结点。

3.4菜单及清屏函数

菜单:

通过两个while循环建立菜单,一个while嵌套在另一个里面,第一个循环为永循环除非碰到break结束循环,第二个while通过一个chooseflag的真假值来判断循环是否继续执行下去。

Choose的值加上IF语句实现选项。

清屏:

建立一个清屏函数的关键在于可由于人的需要判断是否做出清屏操作,靠的是简单的IF语句和系统自带清屏函数组合而成。

关键语句如下:

intinquiry;

if(inquiry==1)

system("cls");

第4章.调试与操作说明

4.1调试情况

在首次运行时出现过一些小的问题,由于程序的复杂难度不大,所以解决起来并不会出现太大的问题不过经过一点点的改正,错误也慢慢地变少。

这也说明做事要认真,尤其做计算机这方面工作的时候,因为计算机不容许不一点点的错误,有了一点小错误和有一个大错误在计算机看来都是一样的,都不会得不到结果。

有些小错误,比如说少了个分号,变量忘了定义,数据溢出等都是些小错误,但也不能松懈。

因为要注意的地方很多,经过多次尝试,问题也就自然而然的解决了,而且以后遇到这方面的问题都会觉得比较得心应手。

出现可被编译器解决的问题容易找出,但出现运行计算过程中的错误就得仔细分析函数步骤的错误,我们在运行过程中曾出现过由于累计报数人数计数器count未被归1,而造出出列顺序的错误,但是只要你细心观察也一定能解决这些看起来很简单却不易于被发现的问题。

测试数据如下三组:

(经计算均为正确值)

1.3,5,2(4)出列顺序为1,2,3

2.2,6,3,4,8

(2)出列顺序为2,4,5,3,1

3.3,1,7,2,4,7,4(20)出列顺序为6,7,4,1,5,3,2

4.2操作说明

4.2.1菜单界面(显示系统时间)

4.2.2进入并实现约瑟夫环问题界面(附带清屏函数)

 

4.2.3进入2了解约瑟夫环问题界面(附带清屏函数)

 

4.2.4不执行清屏操作时的界面

 

4.2.4选择3退出程序的界面

总结

------心得体会

一周的课程设计将要结束了,课程设计弥补了平时学习上被遗忘的一些知识,同时也当作期末考试复习的一部分,约瑟夫环问题,主要是以链表和指针知识为主的编程设计,此次课程设计不但加深了自己对链表认识,同时也了解了更多关于链表在数据结构中的其它应用,从双链表,循环双链表到链栈,链串.自己都有认真去看了一次.指针方面的知识,在C语言中是极其重要的,之前对于指针的使用一直不怎么熟悉,经过这次课程设计之后,指针的使用,基本上都懂了.还有就是各个函数之间的传递和调用,运用起来也比较熟悉了,不像以前那样,不知怎么用.

这次课程设计的最大缺点就是,菜单的设计不应该选择弹出式菜单,因为约瑟夫环这道题目的要求只有三个,把解决约瑟夫环问题的主函数做出来之后,发现代码比较少,当时为了追求代码的数量,才选择了弹出式菜单.不仅花费了不少的时间,而且做出来的菜单也不美观.虽然在功能上是比其它的菜单好,但是对于修改菜单,菜单界面的修改都是挺麻烦的.

刚开始的时候,由于对题目错误的理解,对自己的编程造成了一些影响,里面说到密码,就想到了密码应该包括英文字母,没有注意到括号里面的正整数,如果是英文字母的话,难度相对大一些.开始在这个问题上耗了不少时间,后来在同学的提醒下,把错误修改了过来.

这次课程设计,给了自己很大的帮助,只是一道题目涉及的内容有点少,一道题目只涉及到一两个知识点,如果题目能够涉及到,树,图,栈,队列,串,这些数据结构中的重要知识点,这样对我们的能力培养会更好一点.

 

致谢

这次的课程设计,我们两人一个小组去完成我们自己的课程,但是还是得到了来自很多方面的帮助。

在此首先要感谢淮阴工学院计算机工程系提供给我这次实践的机会,让我们有机会贴近现实,感受成功的喜悦;其次要感谢实验机房的老师提供优良的实验设备供我们做实验,正是这种良好的实验环境让我们整个实验过程心情都非常愉快。

只有在真正实战的时候才会发现书到用时方恨少的真谛。

有时感觉自己那么一次次举手请教,可问题又那么幼稚简单。

最后也要感谢同学们的帮助,有了他们的支持使我遇到任何困难都不是一个人在战斗。

感谢所有在我课程设计过程中帮助过我的人!

 

参考文献

[1]《C程序设计》(第三版)谭浩强著清华大学出版社

[2]《数据结构》(C语言版)严蔚敏著清华大学出版社

[3]《C++面向对象程序设计教程》陈维兴林小茶著清华大学出版社

附录

程序源代码:

#include

#include

#include

#include

#include

#defineNULL0

typedefstructNode

{

intm;//密码

intn;//序号

structNode*next;

}Node,*Linklist;

Linklistcreate(intz)//生成循环单链表并返回,z为总人数

{

inti,mm;

LinklistH,r,s;

H=NULL;

printf("请按顺序依次为每个人添加密码:

");

for(i=1;i<=z;i++)

{

printf("\ninputcipher=");

scanf("%d",&mm);

s=(Linklist)malloc(sizeof(Node));

s->n=i;

s->m=mm;

printf("%d号的密码%d",i,s->m);

if(H==NULL)//从链表的第一个节点插入

{

H=s;

r=H;

}

else//链表的其余节点插入

{

r->next=s;

r=s;//r后移

}//for结束

r->next=H;/*生成循环单链表*/

returnH;

}

 

voidsearch(LinklistH,intm0,intz)//用循环链表实现报数问题

{

intcount=1;//count为累计报数人数计数器

intnum=0;//num为标记出列人数计数器

Linklistpre,p;

p=H;

printf("出列的顺序为:

");

while(num

{

do{

count++;

pre=p;

p=p->next;

}

while(count

{pre->next=p->next;

printf("%d",p->n);

m0=p->m;

free(p);

p=pre->next;

count=1;

num++;

}//while结束

}

voidclean()

{

intsystem(constchar*string);

intinquiry;

printf("请问需要清除上一次操作记录吗(1.清屏/2.不清屏)...?

\n");

scanf("%d",&inquiry);

if(inquiry==1)

system("cls");

}

voidtext()

{

intm0,z,i,choose,k=1;//k用来阻止第一次进入程序清屏操作

LinklistH;

boolchooseFlag=false;

while

(1)

{

if(k!

=1)

clean();

k++;

while(!

chooseFlag)

{

printf("……………………欢迎进入约瑟夫环问题系统……………………\n");

printf("*1.输入约瑟夫环数据*\n");

printf("*2.什么是约瑟夫环*\n");

printf("*3.退出系统*\n");

printf("........................................................\n");

printf("请输入相应的数字进行选择:

");

scanf("%d",&choose);

for(i=1;i<=4;i++)

{

if(choose==i){chooseFlag=true;break;}

elsechooseFlag=false;

}

if(!

chooseFlag)printf("ErrorInput!

\n");

}//endwhile(!

chooseFlag)

if(choose==1)//if开始

{

printf("Inputhowmanypeopleinit:

");//z为总人数

scanf("%d",&z);

if(z<=30)

{

H=create(z);//函数调用

printf("\nInputthestartcodem0=");

scanf("%d",&m0);

search(H,m0,z);

printf("\n\n\n");

}

else

{

printf("超过最大输入人数\n");

break;

}

}

elseif(choose==2)

{

printf("\n约瑟夫环问题:

设有n个人,其编号分别为1,2,3,…,n,安装编号顺序顺时针围坐一圈。

选定一个正整数m,从第一个人开始顺时针报数,报到m时,则此人出列,然后从他的下一个人从1重新报数,依此类推,直到所有人全部出列为止,求出列的顺序。

\n\n");

}

elseif(choose==3)

{

printf("程序结束\n");

break;

}

else

{

printf("错误!

\n");

}//endif

chooseFlag=0;

}//endwhile

(1)

}

voidmain()

{

time_ttimer;/*时间*/

structtm*ptrtime;/*指向structtm的指针*/

timer=time(NULL);/*调用time()函数获取当前时间*/

ptrtime=localtime(&timer);/*调用localtime()函数将获得的系统时间转化为指向structtm的指针指向的结构体*/

printf("系统时间:

%s",asctime(ptrtime));/*用asctime()将结构体转化为字符串输出*/

text();

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1