2.4 约瑟夫问题
(循环链表法实现)
问题描述:
有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一个猴子时,这个猴子就是猴王。编程输入n和m,输出最后猴王的编号。
输入数据:
每行是用空格分开的两个整数,第一个是n,第二个是m(m>0,n<=300)最后一行是0 0.
输出要求:
对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号。
输入样例:
6 2
12 4
8 3
0 0
输出样例:
5
1
7
#include<cstdio>
#include<stdlib.h>
#include<iostream>
using namespace std;
typedef struct Lnode{
int data;
struct Lnode *next;
}Lnode, *LinkList;
//创建循环链表
LinkList creatLinklist(int n)
{
Lnode *head = (Lnode*)malloc(sizeof(Lnode));//创建
head->data = 1;
head->next = NULL;
Lnode *rear = head;
for(int i = 2; i <= n; i++){
Lnode *p = (Lnode*)malloc(sizeof(Lnode));
p->data = i;
p->next = NULL;
rear->next = p;
rear = rear->next;
}
rear->next = head;//首尾相连,构成循环链表
return head;
}
//输入循环链表头指针从khao
void cutline(Lnode *head, int m){
Lnode *r = head;
while(r->next != head)//找到第一个结点的上一个结点
r = r->next;
Lnode *p = head;
while(p->next != p){
for(int i = 1; i < m; i++)//从1开始报数,r指向报m-1的人,p指向报m的人
{
r = p;
p = p->next;
}
r->next = p->next;//摘除p结点
free(p);
p = r->next;
}
cout << p->data << endl;
free(p);
}
int main(){
int m,n;//有n只猴子,数到m退圈
cin >> n >> m;
while(m&&n){
Lnode *L = creatLinklist(n);
cutline(L, m);
cin >> n >> m;
}
system("pause");
return 0;
}