1. 程式人生 > >約瑟夫環問題求解(迴圈連結串列法)

約瑟夫環問題求解(迴圈連結串列法)

#include <stdio.h>
#include <stdlib.h>
typedef struct node{
    int elem;
struct node *next;
}NODE;
int count = 0,n;
void main(int argc,char *argv[]) {
    printf("input num:");
scanf("%d",&n);
while(n<3) {
        printf("input again(num>2):");
scanf("%d", &n);
}

    NODE 
*init(int n); NODE *getout(NODE *head); void display(NODE *head); NODE *head,*p; head = init(n); p=getout(head); display(p); } //將圍成圈的人數按編號存入迴圈連結串列 NODE *init(int n){ NODE *head,*p,*q; head = NULL; p = (NODE *)malloc(sizeof(NODE)); for(int i=1;i<=n;i++){ if(i==1) head = p; else q->next
= p; p->elem = i; q = p; p = (NODE *)malloc(sizeof(NODE)); } q->next = head; return head; } /*遍歷迴圈連結串列,遇到報數3就刪除節點,直到刪除的節點數目只剩一個*/ NODE *getout(NODE *head){ NODE *p,*d; p = head; int num = 1; while(count!=n-1){ //遍歷到只剩一個節點就結束迴圈 /*printf("%d %d\n",p->elem,p->num);*/ if(num==4
) num = 1; if((num+1)==3){ count++; NODE *q; q = p->next; p->next = q->next; free(q); num++; //提前刪除的節點會導致num的自增減少一次,在這裡補上 } num++; d = p; p = p->next; } return d; } void display(NODE *p){ printf("last num:%d",p->elem); }
執行結果

以上是實現程式碼(c)和執行效果

問題:

題目:有n個人圍成一圈,順序排號,從第一個開始報數(從1到3報數),凡報到3的人退出圈子,問最後最後留下的是原來第幾號的那位.

解題思路:

核心思路就是迴圈連結串列儲存元素,然後遍歷(迴圈連結串列如何使用就不贅述),首先將輸入的圍成圈的人數按編號存入迴圈連結串列,然後設定一個變數num來報數,num只能是1~3,遍歷一個num就自增,num加到2的時候就刪除下一個節點,因為下一個節點報數為3,報數到2這次迴圈中,num需要自增兩次,因為下一個節點被刪除了,但實際上被刪除的節點也會參與報數。每找到一個報數3的節點就設定全域性變數count++,當count加到比參與總人數小1的時候就退出迴圈,這個時候迴圈連結串列中只剩下一個節點,該節點裡面的int值就是參與人員的編號。