问题:编号为1、2、···、n的n个人按顺时针方向围坐一圈,每人有一个正整数编号。从某个位置上的人开始报数,数到m的人便出列;下一个人(第m+1个)又从1数起,数到m的人便是第2个出列的人;依次重复下去,直到最后一个人出列,于是得到一个新的次序,试设计程序求出出列顺序。
顺序结构
要点:
1.利用动态数组(末尾释放)及函数移位
2.及时判断是否到末尾,回到开头
#include<iostream>
using namespace std;
void Delete(int a[],int i,int n)
{
for(int j=i;j<n;j++)
a[j]=a[j+1];
}
int main()
{
int m,n,l;
cin>>m>>n;
int *a=new int[n];
l=n;
for (int i = 0; i <l ; i++)
{
a[i]=i+1;
}
//从第K个开始报数
int k = 0;
while (l >0) {
k = k + m;
//报m的人的当前索引位置
k = k % l - 1;
// 判断是否到队尾
if (k < 0) {
cout<<a[l-1];
k = 0;
l--;
} else {
cout<<a[k];
Delete(a,k,l);
l--;
}
}
delete[] a;
cout<<endl;
return 0;
}
单向循环链表结构
要点:
1.建立单向链表,然后将尾指针指向头结点,得到单向循环链表。
2.每数到m出列一个人并删去他。
#include<iostream>
using namespace std;
typedef struct CLinkList
{
int data;
struct CLinkList *next;
}node;
int main()
{
//建立循环链表
node *L,*r,*s;
L = new node;
r =L;
int n,m;
cin>>m;
cin>>n;
int k = m;
for(int i = 1;i<=n;i++) //尾插法建立链表
{
s = new node;
s->data = i;
r->next = s;
r= s;
}
r->next =L->next; //让最后一个结点指向第一个有数据结点
node *p;
p = L->next;
delete L; //删除第一个空的结点
///模拟解决约瑟夫问题
while(p->next != p)
{
for(i = 1;i<k-1;i++)
{
p = p->next;
}
cout<<p->next->data;
p->next = p->next->next; //将该节点从链表上删除。
p = p->next;
}
cout<<p->data<<endl;
return 0;
}