问题描述:
设有编号为1,2,……,n的n个(n>0)个人围成一个圈,从第1个人开始报数,报到m时停止报数,报m的人出圈,才从他的下一个人起重新报数,报到m时停止报数,报m的出圈,……,如此下去,知道剩余1个人为止。当任意给定n和m后,设计算法求n个人出圈的次序。
1.用循环链表实现
完整代码及注释如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct LNode
{
int num;
LNode* next;
}LNode;
typedef LNode* LinkList;
void CreatList(LinkList* L,int n) //创建一个循环列表
{
LinkList p = *L;
p->num = 1;
p->next = NULL;
for(int i = 2;i <= n;i++)
{
LinkList t = (LinkList)malloc(sizeof(LNode));
t->num = i;
p->next = t;
t->next = NULL;
p = t;
}
p->next = *L;
}
void Joseph(LinkList L,int n,int m)
{
int i,j;
LinkList p,t;
p = L;
for(i = 1;i<=n;i++) //在n个人中循环,知道循环结束
{
for(j = 1;j < m;j++) //找到出局的那个人
{
p = p->next;
}
printf("%d->",p->num); //输出出局人的编号
p->num = p->next->num; //轮到下一个人
t = p->next; //使循环链表重新成环
p->next = t->next;
free(t); //free掉出局的人
}
printf("\n");
}
int main() //测试程序
{
LinkList L = (LinkList)malloc(sizeof(LNode));
CreatList(&L,10);
Joseph(L,10,5);
return 0;
}
输出结果如下:
2.用数组方式实现
#include <stdio.h>
int main()
{
int m = 5;
int n = 10;
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0,j = 0;
while(n)
{
i = (i + m -1)%n; //主要就是这个公式,
printf("%d ",a[i]);
for(j = i+1;j < n;j++)
a[j-1] = a[j];
n--;
}
return 0;
}
运行结果为: