Request:
一羣猴子,編號是1,2,3 …m,這羣猴子(m個)按照1-m的順序圍坐一圈。從第1只開始數,每數到第n個,該猴子就要離開此圈,這樣依次下來,直到圈中只剩下最後一隻猴子,則該猴子爲大王。輸入m和n,輸出爲大王的猴子是幾號。
提示:
(1)鏈表解法:可以用一個循環單鏈表來表示這一羣猴子。表示結點的結構體中有兩個成員:一個保存猴子的編號,一個爲指向下一個人的指針,編號爲m的結點再指向編號爲1的結點,以此構成環形的鏈。當數到第n個時,該結點被刪除,繼續數,直到只有一個結點。
(2)使用結構數組來表示循環鏈:結構體中設一個成員表示對應的猴子是否已經被淘汰。從第一個人未被淘汰的數起,每數到n時,將結構中的標記改爲0,表示這隻猴子已被淘汰。當數到數組中第m個元素後,重新從第一個數起,這樣循環計數直到有m-1被淘汰。
(3)該問題爲計算機科學中的經典問題,很多實際的問題可以抽象到這種模型上來。感興趣的同學請搜索“約瑟夫問題”。
#ifndef LIST_H_INCLUDED
#define LIST_H_INCLUDED
typedef int ElemType;
typedef struct LNode{
ElemType data;
struct LNode *next;
}Monkey;
void InitList(Monkey *&L);
void CreateList(Monkey *& L, ElemType a[], int n);
void Pick(Monkey* L, int m, int n);
void DestoryList(Monkey *&L);
#endif // LIST_H_INCLUDED
#include <stdio.h>
#include "list.h"
int main(){
Monkey *Li;
int m, n, i;
scanf("%d%d", &m, &n);
printf("%d猴子以數%d選大王\n",m,n);
ElemType x[m];
for(i=0; i<m; i++)
x[i]=i+1;
CreateList(Li, x, m);
Pick(Li, m, n);
DestoryList(Li);
return 0;
}
#include <stdio.h>
#include "list.h"
#include <malloc.h>
//1.尾插法建鏈表
void CreateList(Monkey *&L, ElemType a[], int n){
Monkey *s, *r; //把r看成結點增量
int i;
L=(Monkey *)malloc(sizeof(Monkey));
r=L;
for(i=0; i<n; i++){
s=(Monkey *)malloc(sizeof(Monkey));
s->data=a[i];
r->next=s;
r=s;
}
r->next=L->next;
}
//2.銷燬線性鏈表
void DestoryList(Monkey *&L){
Monkey *p=L->next;
free(p);
}
//3.選大王
void Pick(Monkey *L, int m, int n){
int k, i;
Monkey *p, *pre;
pre=L,p=L->next;
for(k=0;k<m-1;k++){
for(i=0;i<n-1;i++){
pre=p;
p=p->next;
}
pre->next=p->next;
p=p->next;
}
printf("大王是%d號猴子\n",p->data);
}
Result :
Gain :
void Pick(Monkey *L, int m, int n){
int k, i;
Monkey *p, *pre;
pre=L,p=L->next; //p=L->next
for(k=0;k<m-1;k++){
for(i=0;i<n-1;i++){ //i<n-1
pre=p;
p=p->next;
}
pre->next=p->next;
p=p->next; //p=p->next
}
printf("大王是%d號猴子\n",p->data);
}