DS 线性表4:猴子选大王

这是一个经典的计算机科学问题,称为约瑟夫问题。问题描述是:m个猴子围成一圈,从第1只开始按1到m的顺序数,每数到第n只猴子就离开圈子,直到剩下最后一只猴子成为大王。解法包括使用链表和结构数组模拟过程,直至所有猴子除大王外全部被淘汰。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值