学号
《》
课程设计报告
Josephus环专业:数字媒体技术班级:数字媒体二班姓名:指导教师:成绩:
计算机与信息工程系
2014年 6月 20日
目录
1设计内容及要求1
1.1设计内容1
1.2设计任务及具体要求1
2 概要设计1
2.1介该系统的功能简1
3 程序代码7
4程序调试8
5小结10
1设计内容及要求
1.1设计内容
持有一个密码(正整数)。一 开 始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自 编号为1,2,3,,n的n个人按顺时针方向围成一圈,每个一开始报数。报到m时停止报数。报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个开始,重新从1报数, 如此下去,
直至所有人全部出列为止。设计一个出列顺序。
1.2设计任务及具体要求
利用单向循环链表存储结构模拟约瑟夫过程。按照出列的顺序印出各人的编号。
基本要求:
建立模型,确定存储结构;
对任意n个人,密码为m,实现约瑟夫环问题;
出圈的顺序可以依次输出,也可以用一个数组存储。
2 概要设计
2.1介该系统的功能简
分析功能
约瑟夫环问题是一个古老的数学问题,本次课题要求用序语言的方式解决数学问题。此问题仅使用单循环链表就可以解决此问题。而改进的约瑟夫问题通过运用双向循环链表,同样也能方便地解决。在建立双向循环链表时,因为约瑟夫环的大小由输入决定。为方便操作,我们将每个结点的数据域的值定为生成的结点号时和每个人持有的密码。进行操作时,用一个指针current指向当前的结点,指针front始终指向头结点。然后建立双向循环链表,因为每个人的密码是顺序通过rand()函数随机生成的,所以指定第一个人的顺序号,找到结点,不断地从链表中删除链结点,直到链表剩下最后一个结点,通过一系列的循环就可以解决改进约瑟夫环问题。
为实现上述题目要求及需求,应该用单向循环链表存储结构模拟此过程。
在循环链表的使用中从表的一结点出发找到表中的其他结点。如果从表头指针出发,访问链表的最后一个结点,则必须扫描表中的所有结点。若吧循环表的头指针改用尾指针代替,则从尾指针出发,不仅可以立即访问最后一个结点,而且也可以十分快速方便的找到第一个结点。
抽象数据类型线性表的定义如下:
ADT List { 数据对象:D={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 }
{称 n 为线性表的表长; 称 n=0 时的线性表为空表。}
数据关系:R1={ |ai-1 ,ai∈D, i=2,...,n } {设线性表为的前驱结点来标识这个当前结点呢?这样所有的问题就迎刃而解了。(a1,a2,... ,ai...an)
基本要求:
(1) 人数n、每人的正整数密码、首次报数人编号i、初始报数上限值m均由键盘输入。
(2) 参照线性表的抽象数据类型定义,设计本实验的抽象数据类型。
(3) 根据你设计的抽象数据类型,分别用顺序存储结构和链式存储结构实现约瑟夫环问题。并请分别将顺序存储结构的程序存放在文件test6_Seq.h(基本操作函数)、test6_Seq.cpp(主函数)中,链式存储结构的程序存放在文件test6_Link.h(基本操作函数)、test6_Link.cpp(主函数)中。
接下来思考如何针对约瑟夫环问题建立一个单向循环链表。前面讲的循环链表存在着一些缺点,如添加和删除结点时必须遍历整个链表。添加结点问题在使用尾指针代替头指针后得到了很好的解决,而由于删除结点时必须寻找其前驱结点而导致链表的遍历则需要另外考虑,是否可以使用当前结点。
上面提到了元素的访问,在链表中,大多数是通过链表的头指针依次查找结点并处理数据。单向链表的各种操作非常简单并不需要像顺序表那样移动元素。
此外,需要对读到m的人的信息进行删除,删除操作很简单,它只是把删除点前驱结点的指针域指向删除点后继结点。这里需要注意被删除的结点并没有在内存中真正删除。
3 程序代码
#include
#include
#define N 41 //总人数
#define M 3 //报数大小
#define START 0 // 开始人数所在位置
struct Linklist {
int data;
struct Linklist *link;
} LNode[N];
typedef struct Linklist Linklist;
typedef Li