3 0迴圈鍊錶 約瑟夫環 的建立及C語言實現

2021-09-05 13:08:07 字數 1707 閱讀 9049

無論是靜態鍊錶

還是動態鍊錶

,有時在解決具體問題時,需要我們對其結構進行稍微地調整。比如,可以把鍊錶的兩頭連線,使其成為了乙個環狀鍊錶,通常稱為迴圈鍊錶。

和它名字的表意一樣,只需要將表中最後乙個結點的指標指向頭結點,鍊錶就能成環兒,如圖 1 所示。

圖1 迴圈鍊錶

需要注意的是,雖然迴圈鍊錶成環狀,但本質上還是鍊錶,因此在迴圈鍊錶中,依然能夠找到頭指標和首元節點等。迴圈鍊錶和普通鍊錶相比,唯一的不同就是迴圈鍊錶首尾相連,其他都完全一樣。

約瑟夫環問題,是乙個經典的迴圈鍊錶問題,題意是:已知 n 個人(分別用編號 1,2,3,…,n 表示)圍坐在一張圓桌周圍,從編號為 k 的人開始順時針報數,數到 m 的那個人出列;他的下乙個人又從 1 開始,還是順時針開始報數,數到 m 的那個人又出列;依次重複下去,直到圓桌上剩餘乙個人。

如圖 2 所示,假設此時圓周周圍有 5 個人,要求從編號為 3 的人開始順時針數數,數到 2 的那個人出列:

圖 2 迴圈鍊錶實現約瑟夫環

出列順序依次為:

約瑟夫環問題有多種變形,比如順時針轉改為逆時針等,雖然問題的細節有多種變數,但解決問題的中心思想是一樣的,即使用迴圈鍊錶。

通過以上的分析,我們可以嘗試編寫 c 語言**,完整**如下所示:

#include 

#include

typedef struct nodeperson;

person * initlink(int n)

cyclic->next=head;//首尾相連

return head;

}void findandkillk(person * head,int k,int m)

person * p=head;

//找到編號為k的人

while (p->number!=k)

//從編號為k的人開始,只有符合p->next==p時,說明鍊錶中除了p結點,所有編號都出列了,

while (p->next!=p)

tail->next=p->next;//從鍊錶上將p結點摘下來

printf("出列人的編號為:%d\n",p->number);

free(p);

p=tail->next;//繼續使用p指標指向出列編號的下乙個編號,遊戲繼續

}printf("出列人的編號為:%d\n",p->number);

free(p);

}int main()

輸出結果:

輸入圓桌上的人數n:5

從第k人開始報數(k>1且k<5):3

數到m的人出列:2

出列人的編號為:4

出列人的編號為:1

出列人的編號為:3

出列人的編號為:2

出列人的編號為:5

最後出列的人,即為勝利者。當然,你也可以改進程式,令查詢出最後乙個人時,輸出此人勝利的資訊。

迴圈鍊錶和動態鍊錶唯一不同在於它的首尾連線,這也注定了在使用迴圈鍊錶時,附帶最多的操作就是遍歷鍊錶。

在遍歷的過程中,尤其要注意迴圈鍊錶雖然首尾相連,但並不表示該鍊錶沒有第乙個節點和最後乙個結點。所以,不要隨意改變頭指標的指向。

迴圈鍊錶(約瑟夫環)

約瑟夫環是乙個數學的應用問題 已知n個人 以編號1,2,3.n分別表示 圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列 他的下乙個人又從1開始報數,數到m的那個人又出列 依此規律重複下去,直到圓桌周圍的人全部出列。要通過輸入n,m,k三個正整數,來求出列的序列。這個問題採用的是典型的...

約瑟夫環 C 單項迴圈鍊錶

約瑟夫問題的一種描述是 編號為1 2,n的n個人按順時針方向圍坐一圈,每人持乙個密碼 正整數 一開始任選乙個正整數作為報數上限值m,從第乙個人開始按順時針方向自1開始順序報數,報到m時停止報數。報m的人出列,將他的密碼作為新的m值,從他在順時針方向上的下乙個人開始重新從1報數,如此下去,直至所有人全...

迴圈鍊錶應用 約瑟夫環

約瑟夫環是乙個數學的應用問題 已知n個人 以編號1,2,3.n分別表示 圍坐在一張圓桌周圍。從編號為k的人開始報數,數到m的那個人出列 他的下乙個人又從1開始報數,數到m的那個人又出列 依此規律重複下去,直到圓桌周圍的人全部出列。include includetypedef struct node ...