迴圈列表實現約瑟夫環
阿新 • • 發佈:2021-01-15
迴圈列表實現約瑟夫環
首先我們先上圖幫助理解:(環狀順序佇列)
top
為隊首指標
rear
為隊尾指標
- 我們需要注意,順序佇列在判斷陣列中資料是否存滿時,會出現下面情況:
- 當佇列裡面啥也沒有的時候,佇列的頭指標等於佇列的尾指標(
top==rear
); - 而佇列裡面沒有多餘空間儲存資料的時候,佇列的頭指標也等於佇列的尾指標(
top==rear
);
- 由上我們發現:
- 順序佇列的儲存狀態不同,但是判斷條件相同(
top==rear
)。
-
我們為了區分二者,最簡單的解決辦法是:犧牲掉陣列中的一個儲存空間
-
判斷陣列滿員的條件是:尾指標的下一個位置和頭指標相遇,就說明陣列滿了(
top==(rear+1)
-
迴圈佇列的操作(i. size為順序佇列申請的空間大小 ii.
Q[ ]
為資料集合)
- 入隊(移動尾指標
rear
)rear=(rear+1)%size
Q[rear]=入隊元素
- ❗注意:隊滿時不可入隊
top=(rear+1)%size
- 出隊(移動隊首指標
top
)top=(top+1)%size
Q[top]=出隊元素
- ❗注意:隊空不可出隊
top==rear
- 經上分析,我們可以發現佇列為空時跳出迴圈
實現:
#include<stdio.h>
#include<stdlib.h>
void JosephusRing(int *Q,int n,int s){
//為了不影響主方法中所建立的佇列,所以令宣告兩個指向元素並初始化
int top=0,rear=n;
int i;
while(top-rear){
for(i=0;i<s-1;i++){
//(n+1)--因為填充數值是從 1 開始,所以指向元素移動時,隊尾指向元素的下一個指向為隊首元素的指向,即實際儲存空間大小為 n+1
top=(top+1)%(n+1);
rear=(rear+1)%(n+1);
Q[rear]=Q[top];
}
top=(top+1)%(n+1);
printf ("%3d",Q[top]);
}
}
int main(void){
int *Q;
int n,s;
//輸入儲存個數
printf("please input a num:\n");
scanf("%d",&n);
//輸入出隊元素(第幾個)
printf("please input s:\n");
scanf("%d",&s);
//申請儲存空間
Q=(int *)malloc((n+1)*sizeof(int));
//為了方便我們填充數值為1到n
for(int i=1;i<n+1;i++) Q[i]=i;
//呼叫方法
JosephusRing(Q,n,s);
}
輸出結果展示:
- 由於上述程式碼實現的時間複雜度為O(n2)
為了降低時間複雜度,我們可以引入一個計數器cnt
//降低時間複雜度
#include<stdio.h>
#include<stdlib.h>
void JosephusRing(int *Q,int n,int s){
int top=0,rear=n;
int cnt=1;
while(top-rear){
if(cnt-s){
top=(top+1)%(n+1);
rear=(rear+1)%(n+1);
Q[rear]=Q[top];
cnt++;
}else{
top=(top+1)%(n+1);
printf("%3d",Q[top]);
cnt=1;
}
}
}
int main(void){
int *Q;
int n,s;
printf("please input a num:\n");
scanf("%d",&n);
printf("please input s:\n");
scanf("%d",&s);
Q=(int *)malloc((n+1)*sizeof(int));
for(int i=1;i<n+1;i++) Q[i]=i;
JosephusRing(Q,n,s);
}
執行結果同上!