1、2.1类LinkList32.2类Joseph32.3类异常处理33详细设计和实现33.1创建结点Node33.2创建双向循环链表43.3从链表中删除结点54调试与操作说明54.1调试情况54.2操作说明6总结8致谢9参考文献101需求分析1.1功能分析本次选做的课程设计是改进约瑟夫(Joseph环问题。我选择了和薛晶两个人来完成本次课程设计的作业。约瑟夫环问题是一个古老的数学问题,本次课题要求用程序语言的方式解决数学问题。此问题仅使用单循环链表就可以解决此问题。而改进的约瑟夫问题通过运用双向循环链表,同样也能方便地解决。在建立双向循环链表时,因为约瑟夫环的大小由输入决定。为方便操作,我们将每
2、个结点的数据域的值定为生成结点时的顺序号和每个人持有的密码。进行操作时,用一个指针current指向当前的结点,指针front始终指向头结点。然后建立双向循环链表,因为每个人的密码是通过rand(函数随机生成的,所以指定第一个人的顺序号,找到结点,不断地从链表中删除链结点,直到链表剩下最后一个结点,通过一系列的循环就可以解决改进约瑟夫环问题。1.2设计平台Windows2000以上操作系统;Microsoft Visual C+ 6.02概要设计已知n个人产生每个结点的password。由于每个结点的password是由随机函数产生的,也就是每个结点的password是后知的,所以在一开始人为
3、地指定一个结点的顺序,由此结点开始报数。报password个数后,报到的那个结点被删除,它的password被记录下,由它的下一个结点开始逆方向报数如此循环,直到循环链表里只剩下一个结点,那就是问题所求的结果。具体到问题上,还需要创建一个Joseph类,由构造函数来初始化,输入所有的人数,也就是表长,然后指定由第几个人开始报数。在Joseph类中定义一个GetWinner(函数,由它来实现获得最后的胜利者。并在该类中设置一个判断语句来确定先由顺时针报数并淘汰了一个人之后,再按逆时针顺序报数,如此交替进行。3.1创建结点Node链表都是由一个个结点组成,由于结点的不同,组成的链表也不同。因此需要
4、创建双向链表结点。由于每一个结点有一个密码和一个序号,所以可以将结点结构体定义为:struct Nodeint data。int password。DNode* llink。DNode* rlink。 图3.1 结点Dnode3.2创建双向循环链表创建一个空双向循环链表,双向循环链表和每个结点包括三个域:Element,lLink,rLink.其中element为元素域,rLink域为指向后继结点的指针,新增的lLink域用以指向前驱结点。双向链表也可以带表头结点,并且也可以构成双向循环链表。此时,表头结点的rLink,lLink分别指向双向循环链表的头结点(或表头结点和尾结点。一个结点的lL
5、ink域的指针指向它左边结点的后部,这并不意味着该结点的lLink域保存的仍是该左边结点存储块的起始地址。在此处,指针指向某个结点任何部分都是等价的,都是指该存储块的起始位置。图3.2 单表头的双向循环链表每当结点计数到某一结点时,将他的前驱结点接到他的后继结点,然后将他的密码值password赋给计数变量,再将此结点删除。如此循环下去,直到最后变为空的单循环链表为止。由于当某个人退出圆圈后,报数的工作要从下一个人开始继续,剩下的人仍然是围成一个圆圈的,可以使用循环表,由于退出圆圈的工作对应着表中结点的删除操作,对于这种删除操作频繁的情况,选用效率较高的链表结构,为了程序指针每一次都指向一个具
6、体的代表一个人的结点而不需要判断,链表不带头结点。所以,对于所有人围成的圆圈所对应的数据结构采用一个不带头结点的循环链表来描述。设头指针为front,front始终指向头结点,并定义指针current记录当前的结点。并根据具体情况移动llink-rlink=q-rlink。rlink-llink=q-llink。delete q。来删除当前的那个结点q,通过循环来一次次删除当前的结点,直到链表中剩下最后一个结点。具体程序如下:#includemalloc.hstdlib.htypedef struct node /定义单循环链表中节点的结构 int num。/序列号即个人的编号 int cip
7、her。/个人所持有的密码 struct node *next。linklist。class YSFHpublic: linklist *Creat(int n。 linklist *Select1(int m linklist *head。/头指针指示有n个结点的单循环链表creatprotected: linklist *Select(linklist *head,int mprivate: linklist *p。/存放人员信息 linklist *r。/临时存放 linklist *q。 int k。/*建立单循环链表函数*/linklist *YSFH:Creat(int n p=(
8、linklist *malloc(sizeof(linklist head=p。num=1。 printf(随机产生第1个人的密码: cipher=rand(%10。 if(p-cipher=0 p- %dn,p-cipher r=p。next=p。 for(int k=2。k p=(linklist *num=k。/给每人一个编号 printf(随机产生第%d个人的密码:,k if(p- r- r=p。next=head。 return(head/*决定出列编号*/Select1(int m return Select(head,mSelect(linklist *head,int m q=
9、head。 k=1。 p=q-next。/q为p的前驱指针,p指向当前报数的人出列的序号依次为: /在head中的第一个结点起循环记数找第m个结点 while(q!=p k=k+1。/报一次数 if(k%m=0/所报数等于报数上限值时 printf(%d num/输出该结点的num值 m=p-cipher。/把该结点的cipher(密码值赋给m q-next=p-/对应的节点从链表中删除 free(p k=0。 p=q- else q=p。 p=p-/p指向当前报数的人void main( int n,m。 m!=0。 YSFH Y。输入总人数n: scanf(%d,&n Y.head=Y.Crea
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1