josephu問題
Josephu問題爲:設編號爲1,2,…n的n個人圍坐一圈,約定編號爲k(1<=k<=n)的人從1開始報數,數到m 的那個人出列,它的下一位又從1開始報數,數到m的那個人又出列,依次類推,直到所有人出列爲止,由此產生一個出隊編號的序列,用Go語言進行實現如下:
package main
import (
"fmt"
)
//小孩的結構體
type Boy struct {
No int // 編號
Next *Boy // 指向下一個小孩的指針[默認值是nil]
}
// 編寫一個函數,構成單向的環形鏈表
// num :表示小孩的個數
// *Boy : 返回該環形的鏈表的第一個小孩的指針
func AddBoy(num int) *Boy {
first := &Boy{} //空結點
curBoy := &Boy{} //空結點
//判斷
if num < 1 {
fmt.Println("num的值不對")
return first
}
//循環的構建這個環形鏈表
for i := 1; i <= num; i++ {
boy := &Boy{
No : i,
}
//分析構成循環鏈表,需要一個輔助指針[幫忙的]
//1. 因爲第一個小孩比較特殊
if i == 1 { //第一個小孩
first = boy //不要動
curBoy = boy
curBoy.Next = first //
} else {
curBoy.Next = boy
curBoy = boy
curBoy.Next = first //構造環形鏈表
}
}
return first
}
//顯示單向的環形鏈表[遍歷]
func ShowBoy(first *Boy) {
//處理一下如果環形鏈表爲空
if first.Next == nil {
fmt.Println("鏈表爲空,沒有小孩...")
return
}
//創建一個指針,幫助遍歷.[說明至少有一個小孩]
curBoy := first
for {
fmt.Printf("小孩編號=%d ->", curBoy.No)
//退出的條件?curBoy.Next == first
if curBoy.Next == first {
break
}
//curBoy移動到下一個
curBoy = curBoy.Next
}
}
func StartGame(first *Boy, startNo int, countNum int) {
//1. 空的鏈表我們單獨的處理
if first.Next == nil {
fmt.Println("空的鏈表,沒有小孩")
return
}
//留一個,判斷 startNO <= 小孩的總數
//2. 需要定義輔助指針,幫助我們刪除小孩
tail := first
//3. 讓tail執行環形鏈表的最後一個小孩,這個非常的重要
//因爲tail 在刪除小孩時需要使用到.
for {
if tail.Next == first { //說明tail到了最後的小孩
break
}
tail = tail.Next
}
//4. 讓first 移動到 startNo [後面我們刪除小孩,就以first爲準]
for i := 1; i <= startNo - 1; i++ {
first = first.Next
tail = tail.Next
}
fmt.Println()
//5. 開始數 countNum, 然後就刪除first 指向的小孩
for {
//開始數countNum-1次
for i := 1; i <= countNum -1; i++ {
first = first.Next
tail = tail.Next
}
fmt.Printf("小孩編號爲%d 出圈 \n", first.No)
//刪除first執行的小孩
first = first.Next
tail.Next = first
//判斷如果 tail == first, 圈子中只有一個小孩.
if tail == first {
break
}
}
fmt.Printf("小孩小孩編號爲%d 出圈 \n", first.No)
}
func main() {
first := AddBoy(5)
//顯示
ShowBoy(first)
StartGame(first, 2, 3)
}
運行結果如下:
小孩編號=1 ->小孩編號=2 ->小孩編號=3 ->小孩編號=4 ->小孩編號=5 ->
小孩編號爲4 出圈
小孩編號爲2 出圈
小孩編號爲1 出圈
小孩編號爲3 出圈
小孩小孩編號爲5 出圈
Process finished with exit code 0