Golang(五十一)[線性存儲-鏈表-環形鏈表]

是單向鏈表的特例。將單向鏈表的尾結點,指向第一個數據結點(而不是指向頭結點)

1.初始化

mkdir -p linkList
cd linkList
go mod init linkList
touch linkList.go
vim linkList.go

2.定義環形鏈表結點結構體

// 定義環形鏈表的結點結構體
type LinkNode struct {
	// 定義環形鏈表的數據域
	Data interface{}
	// 定義環形鏈表指針域
	Next *LinkNode
}

3.創建環形鏈表

// 創建環形鏈表
func (node *LinkNode) NewLinkList(data ...interface{}) {
	// 容錯處理
	if node == nil || len(data) == 0 {
		return
	}
	// 保存head結點
	head := node
	// 遍歷data數據創建新結點
	for _, v := range data {
		// 創建新結點,並初始化
		newNode := new(LinkNode)
		newNode.Data = v
		newNode.Next = nil

		// 將當前結點的指針域指向新結點
		node.Next = newNode
		// 更新當前結點
		node = node.Next
	} // 遍歷結束,node在尾結點
	// 將尾結點的指針域指向第一個數據結點(head.Next)
	node.Next = head.Next
	// 將head結點賦值給node,以便node回到head結點位置
	node = head
}

4.打印雙向鏈表

1.遞歸實現

// 正向打印環形鏈表--遞歸實現
var start interface{}

func (node *LinkNode) Print1() {
	// 容錯處理
	if node == nil {
		return
	}
	// 如果是頭結點就給第一個數據結點標記賦值[頭結點的數據域爲nil]
	if node.Data == nil {
		// 做第一個數據結點的標記
		start = node.Next
	}
	// 數據結點的特點:有數據數據域
	if node.Data != nil {
		fmt.Print(node.Data, " ")
		//  遞歸的出口: 此時應該在尾結點[數據域不爲空,],其下一個結點(node.Next)即將回到第一個數據結點
		if node.Next == start {
			// 在遞歸調用出口處打印換行
			fmt.Println()
			return
		}
	}
	// 遞歸實現
	node.Next.Print1()
}

測試

func main() {
	list := new(LinkNode)
	list.NewLinkList(1, 2, 3, 4, 5, 6, 7)
	list.Print1()
}

1.循環實現

// 正向打印環形鏈表--循環實現
func (node *LinkNode) Print2() {
	// 容錯處理
	if node == nil {
		return
	}
	// 定義第一個數據結點的位置標記
	start := node.Next
	for node.Next != nil {
		node = node.Next // 更新node結點位置,在初始時,可以跳過head指針[head結點:沒有數據域(nil),只有指針域(指向第一個數據結點)]
		// 數據結點的特點:有數據數據域
		if node.Data != nil {
			fmt.Print(node.Data, " ")
		}
		// 判斷是否在尾結點(即node.Next是否指向第一個數據結點位置)
		if start == node.Next {
			// 已經在尾結點,直接返回
			return
		}
	}
	// 打印換行
	fmt.Println()
}

測試

func main() {
	list := new(LinkNode)
	list.NewLinkList(1, 2, 3, 4, 5, 6, 7)
	list.Print2()
}

5.獲取雙向鏈表的長度[數據結點長度]

// 獲取數據結點長度
func (node *LinkNode) Length() (length int) {
	// 容錯處理
	if node == nil {
		return
	}
	// 標記第一個數據結點的位置:head結點的下一個結點[node.Next]
	start := node.Next
	for {
		node = node.Next // 初始可以跳過head結點
		length++
		// 如果當前在尾結點,即指針域指向第一個數據結點時
		if start == node.Next {
			break
		}
	}
	/* // 也可以使用如下方法獲取:
	for {
		node = node.Next // 初始跳過head 結點
		if node.Data != nil {
			length++
		}
		// 如果當前在尾結點,即指針域指向第一個數據結點時
		if start == node.Next {
			break
		}
	} */
	return
}

測試

func main() {
	list := new(LinkNode)
	list.NewLinkList(1, 2, 3, 4, 5, 6, 7)
	list.Print1()
	length := list.Length()
	fmt.Println("環形鏈表的數據結點長度爲:", length)
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章