詳解Go語言中單鏈表的使用
鏈表
一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱為結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。使用鏈表結構可以避免在使用數組時需要預先知道數據大小的缺點,鏈表結構可以充分利用計算機內存空間,實現靈活的內存動態管理。但是鏈表失去瞭數組隨機讀取的優點,同時鏈表由於增加瞭結點的指針域,空間開銷比較大。
單鏈表結構
利用 struct 可以包容多種數據類型,結構體內也可以包含多個成員,這些成員可以是基本類型、自定義類型、數組類型,也可以是指針類型。這裡可以使用指針類型成員來存放下一個結點的地址。如以下定義,成員 data 用來存放結點中的數據(整數類型),next 是指針類型的成員,它指向 ListNode struct 類型數據,也就是下一個結點的數據類型。
type ListNode struct { data int next *ListNode }
創建節點
節點聲明和賦值有以下幾種格式:
package main import "fmt" type ListNode struct { data int next *ListNode } func main() { var head *ListNode head = new(ListNode) head.data = 1 var node1 = new(ListNode) node1.data = 2 var node2 = &ListNode{3, nil} var node3 = &ListNode{data: 4} fmt.Println(*head) fmt.Println(*node1) fmt.Println(*node2) fmt.Println(*node3) } /* 輸出: {1 <nil>} {2 <nil>} {3 <nil>} {4 <nil>} */
遍歷鏈表
一個for循環即可,結構描述的鏈表沒有空鏈表的,不論data是何種類型,一旦聲明即使不馬上賦值也會有類型默認值,比如new(ListNode)即賦值瞭ListNode{0, nil}。
func showNode(p *ListNode) { fmt.Print(*p) for p.next != nil { p = p.next fmt.Print("->", *p) } fmt.Println() }
頭插法
新結點放在鏈表的最前面
package main import "fmt" type ListNode struct { data int next *ListNode } func showNode(p *ListNode) { fmt.Print(*p) for p.next != nil { p = p.next fmt.Print("->", *p) } fmt.Println() } func main() { var head = &ListNode{0, nil} for i := 1; i < 5; i++ { var node = ListNode{data: i} node.next = head head = &node } showNode(head) } /* 輸出: {4 0xc000084250}->{3 0xc000084240}->{2 0xc000084230}->{1 0xc000084220}->{0 <nil>} */
尾插法
新結點追加到鏈表的最後面
package main import "fmt" type ListNode struct { data int next *ListNode } func showNode(p *ListNode) { fmt.Print(*p) for p.next != nil { p = p.next fmt.Print("->", *p) } fmt.Println() } func main() { var head, tail *ListNode head = &ListNode{0, nil} tail = head for i := 1; i < 5; i++ { var node = ListNode{data: i} (*tail).next = &node tail = &node } showNode(head) } /* 輸出: {0 0xc000084220}->{1 0xc000084230}->{2 0xc000084240}->{3 0xc000084250}->{4 <nil>} */
遍歷方法
方法的定義:參數表放在函數名前
package main import "fmt" type ListNode struct { data int next *ListNode } func (p *ListNode) travel() { fmt.Print(p.data) for p.next != nil { p = p.next fmt.Print("->", p.data) } fmt.Println("<nil>") } func main() { var head = &ListNode{0, nil} head.travel() for i := 1; i < 10; i++ { var node = ListNode{data: i} node.next = head head = &node } head.travel() var root *ListNode root = new(ListNode) root.travel() } /* 輸出: 0<nil> 9->8->7->6->5->4->3->2->1->0<nil> 0<nil> */
鏈表長度
註意:函數與方法的區別
package main import "fmt" type ListNode struct { data int next *ListNode } func (head *ListNode) size() int { size := 1 for head = head.next; head != nil; size++ { head = head.next } return size } func Len(head *ListNode) int { size := 1 for head = head.next; head != nil; size++ { head = head.next } return size } func main() { var head = &ListNode{0, nil} fmt.Println(Len(head)) fmt.Println(head.size()) for i := 1; i < 10; i++ { var node = ListNode{data: i} node.next = head head = &node } fmt.Println(Len(head)) fmt.Println(head.size()) } /* 輸出: 1 1 10 10 */
鏈表轉數組
package main import ( "fmt" ) type ListNode struct { data int next *ListNode } func (head *ListNode) size() int { size := 1 for head = head.next; head != nil; size++ { head = head.next } return size } func (head *ListNode) tolist() []int { var res []int res = make([]int, 0, head.size()) for head.next != nil { res = append(res, head.data) head = head.next } res = append(res, head.data) return res } func (head *ListNode) tolist2() []int { var res []int res = make([]int, 0, head.size()) res = append(res, head.data) head = head.next for head != nil { res = append(res, head.data) head = head.next } return res } func main() { var head = &ListNode{0, nil} for i := 1; i < 10; i++ { var node = ListNode{data: i} node.next = head head = &node } fmt.Println(head.tolist()) var root, tail *ListNode root = &ListNode{0, nil} tail = root for i := 1; i < 10; i++ { var node = ListNode{data: i} (*tail).next = &node tail = &node } fmt.Println(root.tolist2()) } /* 輸出: [9 8 7 6 5 4 3 2 1 0] [0 1 2 3 4 5 6 7 8 9] */
數組轉鏈表
package main import "fmt" type ListNode struct { data int next *ListNode } func (p *ListNode) travel() { fmt.Print(p.data) for p.next != nil { p = p.next fmt.Print("->", p.data) } fmt.Println("<nil>") } func toNode(list []int) *ListNode { var head, tail *ListNode head = &ListNode{list[0], nil} tail = head for i := 1; i < len(list); i++ { var node = ListNode{data: list[i]} (*tail).next = &node tail = &node } return head } func main() { var lst = []int{1, 3, 2, 3, 5, 6, 6, 8, 9} toNode(lst).travel() } /* 輸出: 1->3->2->3->5->6->6->8->9<nil> */
到此這篇關於詳解Go語言中單鏈表的使用的文章就介紹到這瞭,更多相關Go語言單鏈表內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 淺談java如何實現Redis的LRU緩存機制
- 如何利用Go語言實現LRU Cache
- Go 修改map slice array元素值操作
- 手動實現Redis的LRU緩存機制示例詳解
- C++實現LeetCode(25.每k個一組翻轉鏈表)