1. 程式人生 > >(演算法)C語言模擬約瑟夫環問題

(演算法)C語言模擬約瑟夫環問題

約瑟夫環問題描述

m個人圍坐一圈,每人持有一個數字,從第一個人開始從1報數,報到n(第一輪n任意給定)的人出圈,將n改為這個出圈的人所持有的數字,下個人開始從1報數,繼續報到n的人出列;依次類推直到所有人出圈。

C語言模擬該過程演算法

這裡採用帶有尾結點的迴圈單向連結串列儲存玩家資訊,p和pre兩個指標分別指向報數結點和該結點的直接前驅,並同步移動n-1次,刪除p指向的結點直至連結串列為空即可。

具體程式碼

#include<stdio.h>
#include<stdlib.h>
typedef struct node{
    int id;//玩家編號
    int pw;//玩家持有的數字
    struct node *next;
}node,*LinkList;
/*
用帶頭結點的尾插法建立有n個結點的迴圈連結串列,並返回尾結點
*/
LinkList CreateList(LinkList head,int n){
    head->next = NULL;//頭結點
    head->id = 0;
    node *r = head;//工作指標,跟隨最後一個結點
    for(int i=0;i<n;i++){
        node *S = (node*)malloc(sizeof(node));
        S->id = i+1;
        printf("input player%d's password:\n",i+1);
        scanf("%d",&S->pw);
        r->next = S;
        r = S;
    }
    r->next = head->next;//最後一個結點指向頭結點;
    return r;
}

void play(LinkList tail,int sum,int pw){
    if(sum<1) return;
    else{
        LinkList pre = tail;
        LinkList p = tail->next;
        int n = (pw%sum==0)?sum:pw%sum;//一輪中最少步數
        while(--n){
            pre = p;
            p = p->next;
        }
        pre->next = p->next;
        int newPw = p->pw;
        printf("player%d out!\n",p->id);
        p = p->next;
        play(pre,--sum,newPw);
    }
}

void main(){
    printf("input sum:\n");
    int sum ;
    scanf("%d",&sum);
    LinkList tail = CreateList((LinkList)malloc(sizeof(node)),sum);
    printf("input initPW:\n");
    int pw ;
    scanf("%d",&pw);
    play(tail,sum,pw);
}