用迴圈佇列求解約瑟夫環問題普通形式求解
對比分析
設有n個人站成一圈,其編號為1~n。從編號為1的人開始按順時針方向1、2……迴圈報數,數到m的人出列,然後從出列者的下乙個人重新開始報數,數到m的人又出列,如此重複進行,直到n個人都出列為止。要求輸出這n個人的出列順序。
例子展示:當n=5,m=2時的約瑟夫環問題情況如下
秉承佇列的先進先出原則,我們在此基礎上思考求解方式。
1. n個人圍成圈:先將所有人都放入迴圈佇列中,無論這個迴圈佇列的大小是否超出了n,讓每個出隊的人再進隊,不斷重複達到圍成圈的實際操作;
2. 依次報數:從第乙個人開始依次出隊,出隊一次則用計數變數『i』自增;
3. 數到m的人出列:當i%m==0時,則我們就不用將這個人再進隊了,直接將其放入乙個陣列中,用該陣列來記錄出隊順序;
4. 直到n個人都出列為止:當隊列為空時,也就是佇列中n個人都出列了,此時結束迴圈,輸出陣列內的元素;
以上操作即可完成約瑟夫環問題。
以下為順序佇列的建隊過程,大體一致就不多做解釋了:
#include
using
namespace std;
#define maxze 30
typedef
int elemtype;
typedef
struct
sqqueue;
//1.初始化佇列
void
initqueue
(sqqueue *
&q)//2.刪除佇列
void
destroyqueue
(sqqueue *
&q)//3.判斷是否為空表
bool
queueempty
(sqqueue *q)
//4.入隊
bool
enqueue
(sqqueue *
&q,elemtype e)
//5.出隊
bool
dequeue
(sqqueue *
&q,elemtype &e)
以下是約瑟夫環問題的關鍵求解部分:
(設立如此多的函式是為了讓主函式看起來更簡便)
//6.建立所有人員的編號(主要是為了主函式簡潔)
void
number
(elemtype fir_last,
int n)
//7.所有人排隊
void
queueup
(sqqueue *
&q,elemtype fir,
int n)
}//8.排查報數為m的人
void
seekqueue
(sqqueue *
&q,elemtype last,
int m)
else}}
//9.輸出出隊的順序
void
dispqueue
(elemtype last,
int n)
}
以下是主函式的呼叫部分:
以上即用迴圈佇列求解約瑟夫環問題的全部內容了,接下來我們使用普通的求解方式來對比兩者之間的差異:建立乙個陣列存放所有人的編號,開始用i++不斷迴圈(當i=n時重置i),用num來記數,當num%m==0時,輸出a[i],(也可以)令a[i]=0;在迴圈中跳過數值為0的變數,用sign來記錄總輸出個數,當sign=n時就結束迴圈。
輸入部分從簡了
#include
using
namespace std;
#include
void
fun(
int a,
int n,
int m)
else i++
,num++;}
}int
main()
;int n=12;
//輸入部分從簡了
很清晰的看得到,我們使用第二種方式求解時,針對問題直接設定想要的變數,建立想要的迴圈,暴力求解得出答案,但缺點很明顯,**部分難以解釋清楚用以,且為「一次性**」,不可迴圈利用。
而我們使用第一中方式求解時,我們確定好要使用的資料結構型別等,再根據給定的功能快速得出求解方向,以此清晰明了的求解出問題的答案。而且**是可以重複利用的。
用迴圈鍊錶求解約瑟夫環問題
約瑟夫環問題 已知 n 個人 n 1 圍坐一圓桌周圍,從 1 開始順序編號,從序號為 1 的人開始報數,順時針數到 m 的那個人出列。下乙個人又從 1 開始報數,數到m 的那個人又出列。依此規則重複下去,直到所有人全部出列。請問最後乙個出列的人的初始編號。輸入輸出 輸入人數 n,所報數 m,輸出最後...
JAVA求解約瑟夫環
與前面我們介紹的大多數程式問題一樣,約瑟夫環問題也是來自於乙個故事。這個故事發生在乙個名叫約瑟夫的猶太人身上,據說在羅馬人占領喬塔帕特後,39 個猶太人與約瑟夫及他的朋友躲到乙個洞中,39個猶太人決定寧願死也不要被敵人到,於是決定了乙個自殺方式,41個人排成乙個圓圈,由第1個人 開始報數,每報數到第...
使用單鏈表求解約瑟夫環問題
約瑟夫環 約瑟夫問題 是乙個數學的應用問題 已知n個人 以編號1,2,3.n分別表示 圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列 他的下乙個人又從1開始報數,數到m的那個人又出列 依此規律重複下去,直到圓桌周圍的人全部出列。單鏈表參考 約瑟夫環運作如下 1 一群人圍在一起坐成環狀...