數據結構手把手教學——單向循環鏈表

一、單向循環鏈表

單向循環鏈表也稱約瑟夫鏈表。據說著名猶太曆史學家 Josephus有過以下的故事:在羅馬人佔領喬塔帕特後,39個猶太人與Josephus及他的朋友躲到一個洞中,39個猶太人決定寧願死也不要被敵人抓到,於是決定了一個自殺方式,41個人排成一個圓圈,由第1個人開始報數,每報數到第3人該人就必須自殺,然後再由下一個重新報數,直到所有人都自殺身亡爲止。然而Josephus和他的朋友並不想遵從。首先從一個人開始,越過k-2個人(因爲第一個人已經被越過),並殺掉第k個人。接着,再越過k-1個人,並殺掉第k個人。這個過程沿着圓圈一直進行,直到最終只剩下一個人留下,這個人就可以繼續活着。問題是,給定了和,一開始要站在什麼地方纔能避免被處決?Josephus要他的朋友先假裝遵從,他將朋友與自己安排在第16個與第31個位置,於是逃過了這場死亡遊戲。

單向循環鏈表

二、用C語言實現單向循環鏈表

1、構造存儲結構

typedef int datatype;
typedef struct josephus
{
    datatype data;  /* 數據域 */
    struct josephus *next;  /* 指針域 */
}josephus_list, *josephus_plist;

2、初始化

初始化主要工作:①申請頭結點空間;②head->next=head

初始化

/* 初始化 */
void init_josephus_list(josephus_plist *list)
{
    *list = (josephus_plist)malloc(sizeof(josephus_list));
    if(NULL == *list)
    {
        printf("內存申請失敗\n");
        perror("malloc");   /* 打印內存申請失敗原因 */
        exit(1);
    }
    (*list)->next = *list;   /* 將next設爲NULL,建立空鏈表 */
}

3、插入
鏈表插入

void insert_josephus_list(josephus_plist head, josephus_plist new)
{
    new->next = head->next;
    head->next = new;
}

4、刪除

刪除結點和單向鏈表的刪除思想一樣。

鏈表刪除

void delete_josephus_list(josephus_plist pnode)
{
    josephus_plist dnode;

    dnode = pnode->next;
    pnode->next = dnode->next;
    free(dnode);
}

5、判斷鏈表是否爲空

即判斷head是否等於head->next

/* 判斷是否爲空 */
bool isempty(josephus_plist head)
{
    if(head == head->next)
    {
        return true;
    }
    else
    {
        return false;
    } 
}

5、打印鏈表

void show_josephus_list(josephus_plist head)
{
    josephus_plist p = NULL;
    
    for(p = head; p->next != head; p = p->next)
    {
        printf("%d\t", p->data);
    }
    printf("%d\n", p->data);
}

三、練習題:實現約瑟夫環

1、創建鏈表
/* 創建單向循環鏈表 */
void create_josephus_list(josephus_plist head)
{
    josephus_plist new = NULL;
    josephus_plist p = head;
    int len = 0;
    int i = 0;

    printf("輸入要插入數據的個數:");
    scanf("%d", &len);

    for(i = 0; i < len; i++)
    {
        if (0 == i)
        {
            scanf("%d", &(head->data));
        }
        else
        {
            new = (josephus_plist)malloc(sizeof(josephus_list));
            if(NULL == new)
            {
                printf("內存申請失敗\n");
                perror("malloc");
                exit(1);
            }
            printf("輸入要插入的第%d個數據:", (i+1));
            scanf("%d", &(new->data));
            insert_josephus_list(p, new);
            p = p->next;
        }
        show_josephus_list(head);   /* 打印 */
    }
}
2、實現約瑟夫
/* n是第n個要刪除的結點 */
void josephus(josephus_plist head, int n)
{
    int i = 0;
    josephus_plist p = head;

    while(p != p->next)
    {
        for(i = 0; i < n-2; i++)
        {
            p = p->next;
        }
        printf("-->%d", p->next->data);
        delete_josephus_list(p);
        p = p->next;
    }
    printf("-->%d\n", p->data);
}
3、main函數
int main(void)
{
    josephus_plist head = NULL;        /* 定義一個頭指針 */

    init_josephus_list(&head);   /* 初始化 */
    create_josephus_list(head);  /* 創建單向鏈表 */
    josephus(head, 3);
    return 0;
}
4、實驗結果

實驗結果

四、完整代碼

https://github.com/sanjaywu/DataStructure

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章