報數遊戲是這樣的:有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;
}