天天看點

報數遊戲是這樣的:有n個人圍成一圈,按順序從1到n編好号。從第一個人開始報數,報到m的人退出圈子;下一個人從1開始報數,報到m的人退出圈子。如此下去,如此反複到所有人出列。

報數遊戲是這樣的:有n個人圍成一圈,按順序從1到n編好号。從第一個人開始報數,報到m(<n)的人退出圈子;下一個人從1開始報數,報到m的人退出圈子。如此下去,如此反複到所有人出列。設n個人的編号分别為1,2,……n,列印出列的順序。

【算法分析】

本題可以采用建立标志位的方法求解,但如果使用循環鍊的思想,則解題效率更高。n個人圍城一圈,把一個人看成一個節點,n個人采用連結方式,即每一個節點有一個前繼節點和後繼節點,每一個節點有一個指針指向下一個節點,最後一個節點的指針指向第一個節點。這就是單鍊循環的資料結構。當m個人出列時,将m的前繼節點指針指向m節點的後繼指針節點,即把m節點驅出循環鍊。

1.建立循環連結清單

當用數組實作本體鍊式結構時,數組a【i】作為“指針”變量來使用,a[i]存放下一個節點的位置。

設立指針j指向目前節點,則移動節點過程為j=a[i],當數到m時,m節點對外連結,則a[j]=a[a[j]]。

2.設立指針,指向目前節點,設立計數器,計數數到多少人。

3.沿鍊移動指針,每移動一個節點,計數器的值加一,當計數器的值為m時,則m節點對外連結,計數器的值置為1.

4.重複3,直到n個節點對外連結為止。

【代碼如下】

#include<iostream>
using namespace std;
const int n=10,m=4;//設有十個人,報到4的人出列 
int a[n+1],j=n,k=1,p=0;
int main()
{
	for(int i=1;i<n;i++)
		a[i]=i+1;   //建立連結清單 
	a[n]=1;   //第n個人指向第1個人  ,形成一個環 
	while(p<n)   //n個人均出列為止 
	{
		while(k<m)   //報數   計數器加一  
		{
			j=a[j];
			k++;
		}
		printf("%d",a[j]);  //數到m此人出列  計數器置一 
		p++;  //出列人數加一 
		a[j]=a[a[j]];
		k=1;
	}
	return 0;
}