1. 程式人生 > >數據結構(一)線性表循環鏈表之約瑟夫環

數據結構(一)線性表循環鏈表之約瑟夫環

cli amp tlist isp alloc 個人 pla 初始 ont

(一)前提

41個人報數,1-3,當誰報數為3,誰就去嗝屁。現在獲取他們嗝屁的順序

(二)實現結構

技術分享圖片技術分享圖片技術分享圖片技術分享圖片技術分享圖片

順序:3->1->5->2->4 

(三)代碼實現

技術分享圖片
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int ElemType;
typedef int Status;

typedef 
struct Node { ElemType data; struct Node* next; }Node; typedef struct Node* CLinkList; //四個基本操作,初始,清空,判斷是否為空,獲取長度 Status InitList(CLinkList* L, int n); //指定開始位置來打印數據 void PrintListByIndex(CLinkList rear, int index); //用來打印鏈表 void PrintList(CLinkList rear);
老方法聲明函數,結構體等
int main()
{
    CLinkList L 
= NULL; CLinkList p; ElemType e; int n = 41; int m = 3; int i; InitList(&L,n); //現在L指向第一個結點 PrintList(L); while (L!=L->next) //判斷頭尾指針是否指向相同,相同則元素都不存在 { for (i = 1; i < m-1; i++) L = L->next; //找到要刪除的那個結點的前一個 printf("
%d->", L->next->data); //獲取被殺死的人的數據 p = L->next; //獲取被殺死的人 L->next = p->next; free(p); L = L->next;//指向新的下一個元素 } printf("%d", L->data); //輸出最後一個 free(L); system("pause"); return 0; } //四個基本操作,初始,清空,判斷是否為空,獲取長度 //初始化帶有頭結點的鏈表 Status InitList(CLinkList* L,int n) { CLinkList rear, q; //rear是尾結點 ElemType item; rear = q = NULL; srand(time(0)); for (int i = 0; i < n;i++) { item = rand() % 100; if (*L==NULL) { *L = (CLinkList)malloc(sizeof(Node)); if (!(*L)) return ERROR; (*L)->data = item; (*L)->next = *L; //自己指向自己 rear = *L; //設置尾指針位置 } else { //生成新的節點,根據尾指針添加節點,並實時更新尾指針。註意這裏數據插入是尾插法 q = (CLinkList)malloc(sizeof(Node)); q->data = item; q->next = rear->next; rear->next = q; rear = q; } } return OK; }
技術分享圖片
//用來打印鏈表
void PrintList(CLinkList L)    
{
    CLinkList q = L;    //獲取頭指針
    while (q->next != L)
    {
        printf("%d ", q->data);
        q = q->next;
    }
    printf("%d\n", q->data);
}
老方法打印鏈表PrintList

技術分享圖片

(四)擴展提升

1-N個人,按順時針一圈,每個人手中有一個密碼(一個正整數),
我們(裁判)定義第一個開始值為M,從第一個人開始自1開始報數,直到報數為M,那麽這個人就退出,將他手中的密碼值作為新的開始值,
一直循環直到所有的人都退出

情景演示

技術分享圖片

技術分享圖片技術分享圖片技術分享圖片技術分享圖片技術分享圖片

修改代碼

int main()
{
    CLinkList L = NULL;
    CLinkList p;
    ElemType e;
    int n = 19;
    int m;
    int i;

    InitList(&L, n);        //現在L指向第一個結點
    PrintList(L);

    scanf("%d", &m);    //初始密碼值我們輸入
    m--;    //下面while循環都是由前一結點開始計算距離的,而我們這裏是從第一個結點直接開始的,需要找到他的前一個節點,或者將走的步數減一即可
    while (L != L->next)    //判斷頭尾指針是否指向相同,相同則元素都不存在
    {
        for (i = 1; i <= m - 1; i++)
            L = L->next;    //找到要退出的那個人的前一個人
        printf("%d->", L->next->data);    //獲取將要退出的人的密碼
        p = L->next;    //獲取即將退出的人
        L->next = p->next;
        m = p->data;    //更新密碼值
        free(p);  
     //每次返回的都是退出結點的前一個節點,方便計算當密碼為1的情況(重點)
} printf(
"%d\n", L->data); //輸出最後一個人 free(L); system("pause"); return 0; }

技術分享圖片

數據結構(一)線性表循環鏈表之約瑟夫環