C語言中文網 目錄
首頁 > Go語言教程 > Go語言容器 閱讀:6,624

Go語言list(列表)

< 上一頁Go語言sync.Map 流程控制下一頁 >

列表是一種非連續存儲的容器,由多個節點組成,節點通過一些變量記錄彼此之間的關系。列表有多種實現方法,如單鏈表、雙鏈表等。

列表的原理可以這樣理解:假設 A、B、C 三個人都有電話號碼,如果 A 把號碼告訴給 B,B 把號碼告訴給 C,這個過程就建立了一個單鏈表結構,如下圖所示。


圖:三人單向通知電話號碼形成單鏈表結構

如果在這個基礎上,再從 C 開始將自己的號碼給自己知道號碼的人,這樣就形成了雙鏈表結構,如下圖所示。


圖:三人相互通知電話號碼形成雙鏈表結構

那么如果需要獲得所有人的號碼,只需要從 A 或者 C 開始,要求他們將自己的號碼發出來,然后再通知下一個人如此循環。這個過程就是列表遍歷。

如果 B 換號碼了,他需要通知 A 和 C,將自己的號碼移除。這個過程就是列表元素的刪除操作,如下圖所示。


圖:從雙鏈表中刪除一人的電話號碼

Go 語言中,將列表使用 container/list 包來實現,內部的實現原理是雙鏈表。列表能夠高效地進行任意位置的元素插入和刪除操作。

初始化列表

list 的初始化有兩種方法:New 和聲明。兩種方法的初始化效果都是一致的。

1) 通過 container/list 包的 New 方法初始化 list

變量名 := list.New()


2) 通過聲明初始化list

var 變量名 list.List


列表與切片和 map 不同的是,列表并沒有具體元素類型的限制。因此,列表的元素可以是任意類型。這既帶來遍歷,也會引來一些問題。給一個列表放入了非期望類型的值,在取出值后,將 interface{} 轉換為期望類型時將會發生宕機。

在列表中插入元素

雙鏈表支持從隊列前方或后方插入元素,分別對應的方法是 PushFront 和 PushBack。

提示

這兩個方法都會返回一個 *list.Element 結構。如果在以后的使用中需要刪除插入的元素,則只能通過 *list.Element 配合 Remove() 方法進行刪除,這種方法可以讓刪除更加效率化,也是雙鏈表特性之一。

下面代碼展示如何給list添加元素:
l := list.New()

l.PushBack("fist")
l.PushFront(67)
代碼說明如下:
  • 第 1 行,創建一個列表實例。
  • 第 3 行,將 fist 字符串插入到列表的尾部,此時列表是空的,插入后只有一個元素。
  • 第 4 行,將數值 67 放入列表。此時,列表中已經存在 fist 元素,67 這個元素將被放在 fist 的前面。

列表插入元素的方法如下表所示。
方  法 功  能
InsertAfter(v interface {}, mark * Element) * Element 在 mark 點之后插入元素,mark 點由其他插入函數提供
InsertBefore(v interface {}, mark * Element) *Element 在 mark 點之前插入元素,mark 點由其他插入函數提供
PushBackList(other *List) 添加 other 列表元素到尾部
PushFrontList(other *List) 添加 other 列表元素到頭部

從列表中刪除元素

列表的插入函數的返回值會提供一個 *list.Element 結構,這個結構記錄著列表元素的值及和其他節點之間的關系等信息。從列表中刪除元素時,需要用到這個結構進行快速刪除。

列表操作元素:
package main

import "container/list"

func main() {
    l := list.New()

    // 尾部添加
    l.PushBack("canon")

    // 頭部添加
    l.PushFront(67)

    // 尾部添加后保存元素句柄
    element := l.PushBack("fist")

    // 在fist之后添加high
    l.InsertAfter("high", element)

    // 在fist之前添加noon
    l.InsertBefore("noon", element)

    // 使用
    l.Remove(element)
}
代碼說明如下:
第 6 行,創建列表實例。
第 9 行,將 canon 字符串插入到列表的尾部。
第 12 行,將 67 數值添加到列表的頭部。
第 15 行,將 fist 字符串插入到列表的尾部,并將這個元素的內部結構保存到 element 變量中。
第 18 行,使用 element 變量,在 element 的位置后面插入 high 字符串。
第 21 行,使用 element 變量,在 element 的位置前面插入 noon 字符串。
第 24 行,移除 element 變量對應的元素。

下表中展示了每次操作后列表的實際元素情況。

列表元素操作的過程
操作內容 列表元素
l.PushBack("canon") canon
l.PushFront(67) 67, canon
element := l.PushBack("fist") 67, canon, fist
l.InsertAfter("high", element) 67, canon, fist, high
l.InsertBefore("noon", element) 67, canon, noon, fist, high
l.Remove(element) 67, canon, noon, high

遍歷列表——訪問列表的每一個元素

遍歷雙鏈表需要配合 Front() 函數獲取頭元素,遍歷時只要元素不為空就可以繼續進行。每一次遍歷調用元素的 Next,如代碼中第 9 行所示。
l := list.New()

// 尾部添加
l.PushBack("canon")

// 頭部添加
l.PushFront(67)

for i := l.Front(); i != nil; i = i.Next() {
    fmt.Println(i.Value)
}
代碼輸出如下:
67
canon

代碼說明如下:
  • 第 1 行,創建一個列表實例。
  • 第 4 行,將 canon 放入列表尾部。
  • 第 7 行,在隊列頭部放入 67。
  • 第 9 行,使用 for 語句進行遍歷,其中 i:=l.Front() 表示初始賦值,只會在一開始執行一次;每次循環會進行一次 i!=nil 語句判斷,如果返回 false,表示退出循環,反之則會執行 i=i.Next()。
  • 第 10 行,使用遍歷返回的 *list.Element 的 Value 成員取得放入列表時的原值。
< 上一頁Go語言sync.Map 流程控制下一頁 >

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo