數據結構之GO環形鏈表解決josephu(約瑟夫)問題

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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章