约瑟夫环三种做法

声明:图片及内容基于https://www.bilibili.com/video/av78358478

题目概述

 

 

循环链表实现

#include<bits/stdc++.h>
using namespace std;
typedef struct node{
    int data;
    struct node *next;
}Node,*Point;          //typedef给链表起小名 
int main(){
    int n,m;       //n只猴子数到m 
    int count=0;       //answer的数组下标 
    int answer[301];   //储存答案 
    while(1){          //保持循环 
        cin>>n>>m;
        if(n==0||m==0) break;     //循环终止 
        else{
            Point head,tail,p,q;        //注意用小名声明结构体指针不要加 *   (初始化头节点)
            head=(Point)malloc(sizeof(Node));  //开辟哨兵节点 
            head->next=NULL;
            tail=head;                  //尾指针指向哨兵节点 
            for(int i=0;i<n;i++){              //以下是尾插法建立链表   (初始化链表,每个节点的数据域是猴子编号,从1到n)
                p=(Point)malloc(sizeof(Node)); //data是猴子的序号从1到n 
                p->data=i+1;
                tail->next=p;
                p->next=head->next;           //循环链表 
                tail=p;                   //tail始终指向最后一个元素 
            } 
            p=head->next;                //p指向第一个数据结点(非哨兵) 
            q=tail;                         //q是p的前驱 
            int i=1;                     //i记录数到几了 
            while(q!=p){  //只要前后指针没相遇即链表有两个以上节点  
                if(i==m){
                    q->next=p->next;
                    free(p);            //释放空间 
                    p=q->next;
                    i=1;                //重新开始数 
                }else{
                    q=p;
                    p=p->next;
                    i++;
                }
            }
            answer[count++]=p->data;
            free(p);                   //别忘了把最后一个空间释放 
            head->next=NULL;           //每次让头节点next为NULL是好习惯
        }
    }
    for(int j=0;j<count;j++){           //输出答案
        cout<<answer[j]<<endl;
    }
}

数组标志位实现

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
using namespace std;
int main() {
    int n, m;
    int number;   //number=n
    int count=1;  //报数
    int i, pos;   //pos是数组下标
    int ans[301], answer = 0;
    while (~scanf("%d%d", &n, &m)) {
        if (n == 0 || m == 0) break;
        number = n;
        int monkey[301] = { 0 };
        for ( i = 0; i < n; i++) {
            monkey[i] = i + 1;      //monkey数组存的是猴子标号
        } 
        pos = 0;
        while (number > 1) {        //存活多余一只猴子
            if (monkey[pos] > 0) {  //如果猴子活着
                if (count != m) {   //报数未到
                    count++;
                    pos = (pos + 1) % n;
                }
                else {
                    monkey[pos] = 0; //杀死
                    count = 1;       //重新报数
                    number--;        //猴子存活数减一
                    pos = (pos + 1) % n;
                }
            }
            else {
                pos = (pos + 1) % n;
            }
        }
        for ( i = 0; i < n; i++) {
            if (monkey[i] > 0) {
                //printf("%d\n", monkey[i]);
                ans[answer++] = monkey[i];
            }
        }
    }
    for (i = 0; i<answer; i++) {
        cout << ans[i] << endl;
    }
    return 0;
}

数组模拟链表

#include<iostream>
using namespace std;
int main() {
    int n, m;
    int ans[301], answer = 0;
    while (1) {
        cin >> n >> m;
        if (n == 0 || m == 0) break;
        int count = 1;         //报数
        int pos = 0;           //数组前置下标
        int prior = n - 1;     //数组后置下标
        int monkey[301] = { 0 };
        for (int i = 0; i < n; i++) {
            monkey[i] = (i + 1) % n;  //是最后一个数据下标为0,实现模拟
        }                             //循环链表
        int number = n;
        while (number > 1) {
                if (count != m) {     //如果报数没到m,pos和prior都向后移动
                    prior = pos;
                    pos = monkey[pos];//monkey[pos]存有pos的下一个位置
                    count++;          //报数加一
                }
                else {
                    number--;         //杀死
                    count = 1;        //重新报数
                    monkey[prior] = monkey[pos]; //prior的下一位置变为原来pos的下一位置,跳过pos
                    pos = monkey[pos]; //pos后移一位
                }
        }
        ans[answer++] = monkey[pos]+1; //注意加一
    }
    for (int i = 0; i < answer; i++) {
        cout << ans[i] << endl;
    }
    return 0;
}

最后的状态

posted @ 2021-03-09 01:23  gonghr  阅读(207)  评论(0)    收藏  举报