项目名称: 报数游戏

一、问题的提出
n个人围成一圈,从1到n编上号,开始报数:凡是报到m的淘汰出局。若是你,你选择几号,将被最终留下。
二、设计方案
这是一个循环报数问题,故要找一个能循环数数的数据结构来解决。
方案一
单循环链表解决。创建一个n个结点的单循环链表,其值域分别为1到n 。从第一个结点开始报数,凡是报到m的,其值域置为0且n减1。下次数到值域为0的结点时,将其隔过去,数下一个结点,当数到m时,将该结点的值域置为0且n减1,依次进行下去,直到n为1。输出值域不为0的结点的值域,就是我们要选择的编号。
方案二
双循环链表解决。创建一个n个结点的双循环链表,其值域分别为1到n 。从第一个结点开始报数,凡是报到m的,将该结点删除,继续报数,报到m的,将该结点删除,这样进行下去,直到链表中只剩一个结点。输出第一个结点的值域,就是我们要选择的编号。
方案三
一维数组解决。定义一个长度为n的一维数组,元素值分别为1到n,即a[0]=1,a[1]=2,a[2]=3......a[n-1]=n。下标从t=0开始,寻找出列元素的下标为t+m-1,为保证循环报数,取模:(t+m-1)%当前圈中人数。然后将其从数组中删除。当数组中剩下一个元素时,循环结束,输出该元素的值,就是我们要选择的编号。
方案四
队列解决。创建一个具有n个结点的队列的链式结构。报数时,凡是报1--m-1的做出队、入队操作,而报m的只做出队操作,这样依次进行下去,当队列中只剩下一个元素时,循环结束,输出该元素的值,就是我们要选择的编号。
三、流程(实现举例)
方案一


n=4,m=3,count=0,p指向第一个结点
如果*p结点的值域为0或*p结点是head结点,p后移,直到*p结点的值域不为0且不是head结点。
count++; 判断count是否m的倍数,若是,将*p结点的值域置为0。p后移

 


count为3,是m的倍数,将*p结点的值域置为0,p后移。 重复上述操作。

*p是head结点,p后移,直到*p不是head结点且值域不为0。
此时count为4。

count为6,是m的倍数,将*p结点的值域置为0,p后移。
重复上述操作

count为9,是m的倍数,将*p结点的值域置为0,p后移。
此时,值不为0的结点只有一个,循环结束,输出该结点的值域。

 

方案二


创建双循环链表,p指向第一个结点,count初值为0。
如果*p结点是head结点,p后移。
否则,count++。判断count是否为m的倍数,若是,删除该结点;若不是,p后移。

count为3,是m的倍数,删除该结点。
删除方法:q=p; p=q->next; p->prior=q->prior; q->prior->next=p; free(q);

*p不是head结点,count++,p后移。

*p是head结点,p只后移,不计数,count仍为4。

count为6,是m的倍数,删除该结点。

重复上述操作步骤。

count为9,是m的倍数,删除该结点。

此时只剩下一个结点,循环结束。输出第一个结点的值域。

 

方案三


数组初始化,元素值分别为1、2、3、4。n表示当前元素个数,初值为4。
开始寻找要出列的元素的下标t,t的初值为0。
因为m的倍数出列,故出列元素的下标为(t+m-1)%n。
所以第一次淘汰的t=(t+m-1)%n=(0+3-1)%3=2。

删除下标为t的元素,元素个数减1。n=n-1=3。

方案四:
创建一个链队,从头到尾结点的值域分别为1、2、3、4
t的初值为1,当t<m时,做出队、入队操作,且t++。
故编号1的结点出队入队,t=2;编号2的结点出队入队,t=3。
队首元素出队

t的初值为1,当t<m时,做出队、入队操作,且t++。
故编号4的结点出队入队,t=2;编号1的结点出队入队,t=3。

 


队首元素出队

t的初值为1,当t<m时,做出队、入队操作,且t++。
故编号4的结点出队入队,t=2;编号1的结点出队入队,t=3。

队首元素出队

链队中只剩下一个元素,循环结束。输出队首元素。
四、知识储备
1、数组。数组的定义、初始化、下标法表示数组元素及取模运算。
2、链表。链表的初始化、尾插法创建链表、链表的遍历及链表的删除。(注意单循环链表和双循环链表在操作上的异同)。
3、队列。队列的初始化、创建一个链队、出队、入队操作。
4、循环控制结构。
5、函数。函数的定义、函数的调用。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值