天天看點

循環連結清單——約瑟夫環實作

近期重溫資料結構,發現有不少書籍沒有将成品可運作的資料結構代碼放出,是以在這挖個坑,後期會将常見資料結構以C語言形式實作,并且盡可能讓隻看了書但是代碼能力較弱的讀者也能看懂實作。本人能力有限,不足之處還請大家多多指出。

循環連結清單——約瑟夫環實作

下面放出循環連結清單實作的約瑟夫環,運作環境為vs2019,無報錯

#include<stdio.h>
#include<stdlib.h>
#pragma warning(disable:4996);
//約瑟夫環問題實作
typedef struct Node {//建立結點
    int data;
    struct Node* next;
}Node, * Point;
void tailcreate(Point* head, int n) {//建立結點個數為n的連結清單,思想為先來後到,不斷把新結點放在連結清單尾(尾插)
    Point p, s;
    p = *head;//循環指針p從頭結點開始
    for (int i = 2; i <= n; i++) {
        s = (Point)malloc(sizeof(Node));
        s->data = i;
        p->next = s;//把新結點連在頭節點的後面
        p = s;//此時新結點s變成了最後的結點,讓下一個結點在s的後面插入,循環往複
    }
    p->next = *head;
}
void find(Point* head, int lotcation, int num) {//location為從第幾個開始,num為數到幾
    Point p = *head;
    Point s;
    for (int i = 0; i < lotcation - 1; i++) {//此時p移動到了第location位置的結點
        p = p->next;
    }
    printf("第%d個結點的資料是%d\n", lotcation, p->data);
    while (1) {//每次循環删除一個結點,直到隻剩一個結點
        if (p == p->next) {
            printf("最後勝利者是%d", p->data);
            break;
        }
        else {
            for (int j = 0; j < num - 2; j++) {//開始計數,p移動到被删除的結點的前一個結點
                p = p->next;
            }
            printf("出列資料是%d\n", p->next->data);
            s = p->next;
            p->next = p->next->next;//将被删除結點的後一個結點與被删除結點的前一個結點連結起來
            free(s);//釋放被删除結點的空間
            p = p->next;//此時讓p移動到被删除結點的下一個結點
        }
    }
}
int main() {
    Point head;
    int num, k, m;
    head = (Point)malloc(sizeof(Node));/*申請一塊Node類型大小的記憶體,
            并強制轉化為結點指針類型,建立頭結點head*/
    head->data = 1;
    head->next = NULL;
    
    
    printf("參與人數:\n");
    scanf("%d", &num);
    printf("從編号幾開始:\n");
    scanf("%d", &k);
    printf("數到幾的出列:\n");
    scanf("%d", &m);
    tailcreate(&head, num);
    find(&head, k, m);
    return 0;
}
           
循環連結清單——約瑟夫環實作

繼續閱讀