已知n个人围坐在一张圆桌周围,从编号为1的人开始报数,数到m的那个人出列。下一个人从1开始报数,数到m的人继续出列,以此类推直至全部人出列。求出列顺序?
解决方案:
1、最简单明了的办法就是用循环链表存储这n个人。数到m的人出列,只需将该结点从链表里剔除即可,然后继续往后报数,直到链表只剩下一个结点时结束。
具体代码如下:
typedef struct People
{
int number;
People *next;
}//结点的存储结构
void List_kind(People* L,int n,int m)
{/////////////////////////////////////////////L为n个人构成的链表,报数报到m的人出列
People *q,*p=L;///////////////////////////p指向当前结点,q指向p的前驱
while(p->next != p)///////////////////////当链表只剩下一个结点,即报数剩下一个人的时候结束。
{
for(int i=1;i<m;i++)
{/////////////////////////////////////for循环实现功能:使p指向要出列的结点,q指向p的前驱
q=p;
p=p->next;
}
printf("%d\n",p->number);
q->next=p->next;//////////////////////将要出列的结点从链表“剔除”
free(p);
p=q->next;////////////////////////////p指向出列的下一个结点,重新开始报数
}
printf("%d\n",q->number);/////////////////输出最后一个人
free(q);
}
第二种办法就是用数组存储,难度将大大增加。但思路还是跟链表有点相似的。首先将要出列的元素输出,然后将它后面的所有元素都向前移一位,将已出列的元素填充掉。然后再向后找下一个要出列的元素。
注意:当搜索到最后一个元素a[i]以后,用求余”%”功能,让数组和循环链表一样实现循环。另外,每次输出一个元素并把它填充掉以后,数组的总元素个数i会减一。
void Array_kind(int n,int m)
{/////////////////////////////////////////////////////////n个人进行报数,报到m的出列
int *a,i,j,k;
a=(int*)malloc(sizeof(int));//////////////////////////为数组a动态分配内存
for(i=1;i<=n;i++)
a[i]=i;///////////////////////////////////////////对每个元素进行编号,代表每个人,注意编号从a[1]开始
for(i=n,k=1;i>=1;i--)/////////////////////////////////i为数组当前元素总个数
{
k=(k+m-1)%i;//////////////////////////////////////令k指向要出列的元素
if(k==0)//////////////////////////////////////////从上式知,当k+m-1=i时才会(k+m-1)%i=0。因为数组是从a[1]开始的,k=0时出列的元素应该是a[i],而不是a[0]。
k=i;
printf("%d\n",a[k]);//////////////////////////////输出要出列的元素
for(j=k;j<i;j++)//////////////////////////////////k之后的元素都向前移一位,填充出列元素的位置。
a[j]=a[j+1];
}
}
java实现,使用链表进行移除:
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Yue {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入总人数:");
int totalNum = scanner.nextInt();
System.out.print("请输入报数的大小:");
int cycleNum = scanner.nextInt();
yuesefu(totalNum, cycleNum);
scanner.close();
}
public static void yuesefu(int totalNum, int countNum) {
// 初始化人数
List<Integer> start = new ArrayList<Integer>();
for (int i = 1; i <= totalNum; i++) {
start.add(i);
}
// 从第K个开始计数
int k = 0;
while (start.size() > 0) {
k = k + countNum;
// 第m人的索引位置
k = k % (start.size()) - 1;
// 判断是否到队尾
if (k < 0) {
System.out.println(start.get(start.size() - 1));
start.remove(start.size() - 1);
k = 0;
} else {
System.out.println(start.get(k));
start.remove(k);
}
}
}
}