約瑟夫環問題求解(迴圈連結串列法)
阿新 • • 發佈:2019-02-15
#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值就是參與人員的編號。