c语言课程设计.docx
《c语言课程设计.docx》由会员分享,可在线阅读,更多相关《c语言课程设计.docx(9页珍藏版)》请在冰豆网上搜索。
![c语言课程设计.docx](https://file1.bdocx.com/fileroot1/2022-12/1/85b7704f-7d96-4925-ba8c-83de771378d6/85b7704f-7d96-4925-ba8c-83de771378d61.gif)
c语言课程设计
学号
2013-2014学年第二学期
《高级语言程序设计》
课程设计报告
题目:
Josephus环
专业:
数字媒体技术
班级:
数字媒体二班
姓名:
指导教师:
成绩:
计算机与信息工程系
2014年6月20日
目录
1设计内容及要求1
1.1设计内容1
1.2设计任务及具体要求1
2概要设计1
2.1介该系统的功能简1
3程序代码7
4程序调试8
5小结10
11设计内容及要求
1.1设计内容
持有一个密码(正整数)。
一开始任选一个正整数作为报数的上限值m,从第一个人开始按顺时针方向自编号为1,2,3,,n的n个人按顺时针方向围成一圈,每个一开始报数。
报到m时停止报数。
报m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个开始,重新从1报数,如此下去,
直至所有人全部出列为止。
设计一个出列顺序。
1.2设计任务及具体要求
利用单向循环链表存储结构模拟约瑟夫过程。
按照出列的顺序印出各人的编号。
基本要求:
(1)建立模型,确定存储结构;
(2)对任意n个人,密码为m,实现约瑟夫环问题;
(3)出圈的顺序可以依次输出,也可以用一个数组存储。
2概要设计
2.1介该系统的功能简
分析功能
约瑟夫环问题是一个古老的数学问题,本次课题要求用序语言的方式解决数学问题。
此问题仅使用单循环链表就可以解决此问题。
而改进的约瑟夫问题通过运用双向循环链表,同样也能方便地解决。
在建立双向循环链表时,因为约瑟夫环的大小由输入决定。
为方便操作,我们将每个结点的数据域的值定为生成的结点号时和每个人持有的密码。
进行操作时,用一个指针current指向当前的结点,指针front始终指向头结点。
然后建立双向循环链表,因为每个人的密码是顺序通过rand()函数随机生成的,所以指定第一个人的顺序号,找到结点,不断地从链表中删除链结点,直到链表剩下最后一个结点,通过一系列的循环就可以解决改进约瑟夫环问题。
为实现上述题目要求及需求,应该用单向循环链表存储结构模拟此过程。
在循环链表的使用中从表的一结点出发找到表中的其他结点。
如果从表头指针出发,访问链表的最后一个结点,则必须扫描表中的所有结点。
若吧循环表的头指针改用尾指针代替,则从尾指针出发,不仅可以立即访问最后一个结点,而且也可以十分快速方便的找到第一个结点。
抽象数据类型线性表的定义如下:
ADTList{数据对象:
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
#defineN41//总人数
#defineM3//报数大小
#defineSTART0//开始人数所在位置
structLinklist{
intdata;
structLinklist*link;
}LNode[N];
typedefstructLinklistLinklist;
typedefLinklist*link;
intmain(void)
{
inti;
linkp;
for(i=0;iLNode[i].data=i+1;
if(iLNode[i].link=&LNode[i+1];
else
LNode[i].link=LNode;
}//构建循环链表
p=&LNode[START];//使指针指向开始的人的位置
while(p->link!
=p){
for(i=1;ip=p->link;
p->link=p->link->link;//报中数字的人出列
printf("第%d人出列\n",p->link->data);
p=p->link;
}
getchar();
return0;
}
4程序调试
约瑟夫问题实现算法分析:
采用单项循环链表的数据结构,即将链表的尾元素指针指向链首元素,每一个结点除了指针域外,还有两个域分别存放每一个人的编号和所持有的密码。
解决问题的基本步骤如下。
建立n个结点(无头结点)的单向循环链表。
从链表第一个结点起循环计数,寻找第m个结点。
输出该结果点的id值将该结点的password作为新的m值,删除该结点。
根据m值不断从循环链表中删除结点,直到链表为空。
5小结
这次课程设计心得收获:
一开始接触课程设计感觉真的很难,很多都不懂,不光是逻辑方面的问题,还有就是不具备动手能力,看到不会的,心里就会很乱,甚至感到焦虑。
比如这个题目,刚开始,想法挺多,但考虑如何从逻辑上实现它,
顺序表必须占用一整块预先分配的存储空间,而链表则不需要。
链表在逻辑上相邻的元素在物理位置上可以不相邻,就好比使用排队机进行排队的银行,人们办理业务的顺序是由手上的小纸条的号码来决定的。
在许多特定的场合,使用使用链表优于使用顺序表。
要如何编写程序,可以说几乎是无从下手,参考其他书籍,仿照他们一步一步做下来后,现在对单链表的一些操作熟练了许多。
使我明白了,光靠理论知识是远远不够的,更多的是要靠实际的动手能力。
在以后的学习中会遇到许多相似的算法设计的问题,需要我们多了解有关算法的基本设计思想,以及实现算法的详细步骤。
在以后的学习过程中,要认真学会专业课,多在实践中锻炼自己。
在写编程时,多一些耐心,避免浮躁。
同时考虑问题要全面。
在课余时间多在机上调试。