新聞中心
列表是一種非連續(xù)的存儲(chǔ)容器,由多個(gè)節(jié)點(diǎn)組成,節(jié)點(diǎn)通過(guò)一些變量記錄彼此之間的關(guān)系,列表有多種實(shí)現(xiàn)方法,如單鏈表、雙鏈表等。

列表的原理可以這樣理解:假設(shè) A、B、C 三個(gè)人都有電話號(hào)碼,如果 A 把號(hào)碼告訴給 B,B 把號(hào)碼告訴給 C,這個(gè)過(guò)程就建立了一個(gè)單鏈表結(jié)構(gòu),如下圖所示。
圖:三人單向通知電話號(hào)碼形成單鏈表結(jié)構(gòu)
如果在這個(gè)基礎(chǔ)上,再?gòu)?C 開(kāi)始將自己的號(hào)碼告訴給自己所知道號(hào)碼的主人,這樣就形成了雙鏈表結(jié)構(gòu),如下圖所示。
圖:三人相互通知電話號(hào)碼形成雙鏈表結(jié)構(gòu)
那么如果需要獲得所有人的號(hào)碼,只需要從 A 或者 C 開(kāi)始,要求他們將自己的號(hào)碼發(fā)出來(lái),然后再通知下一個(gè)人如此循環(huán),這樣就構(gòu)成了一個(gè)列表遍歷的過(guò)程。
如果 B 換號(hào)碼了,他需要通知 A 和 C,將自己的號(hào)碼移除,這個(gè)過(guò)程就是列表元素的刪除操作,如下圖所示。
圖:從雙鏈表中刪除一人的電話號(hào)碼
在Go語(yǔ)言中,列表使用 container/list 包來(lái)實(shí)現(xiàn),內(nèi)部的實(shí)現(xiàn)原理是雙鏈表,列表能夠高效地進(jìn)行任意位置的元素插入和刪除操作。
初始化列表
list 的初始化有兩種方法:分別是使用 New() 函數(shù)和 var 關(guān)鍵字聲明,兩種方法的初始化效果都是一致的。
1) 通過(guò) container/list 包的 New() 函數(shù)初始化 list
變量名 := list.New()
2) 通過(guò) var 關(guān)鍵字聲明初始化 list
var 變量名 list.List
列表與切片和 map 不同的是,列表并沒(méi)有具體元素類(lèi)型的限制,因此,列表的元素可以是任意類(lèi)型,這既帶來(lái)了便利,也引來(lái)一些問(wèn)題,例如給列表中放入了一個(gè) interface{} 類(lèi)型的值,取出值后,如果要將 interface{} 轉(zhuǎn)換為其他類(lèi)型將會(huì)發(fā)生宕機(jī)。
在列表中插入元素
雙鏈表支持從隊(duì)列前方或后方插入元素,分別對(duì)應(yīng)的方法是 PushFront 和 PushBack。
提示
這兩個(gè)方法都會(huì)返回一個(gè) *list.Element 結(jié)構(gòu),如果在以后的使用中需要?jiǎng)h除插入的元素,則只能通過(guò) *list.Element 配合 Remove() 方法進(jìn)行刪除,這種方法可以讓刪除更加效率化,同時(shí)也是雙鏈表特性之一。
下面代碼展示如何給 list 添加元素:
l := list.New()
l.PushBack("fist")
l.PushFront(67)代碼說(shuō)明如下:
- 第 1 行,創(chuàng)建一個(gè)列表實(shí)例。
- 第 3 行,將 fist 字符串插入到列表的尾部,此時(shí)列表是空的,插入后只有一個(gè)元素。
- 第 4 行,將數(shù)值 67 放入列表,此時(shí),列表中已經(jīng)存在 fist 元素,67 這個(gè)元素將被放在 fist 的前面。
列表插入元素的方法如下表所示。
| 方 法 | 功 能 |
|---|---|
| InsertAfter(v interface {}, mark * Element) * Element | 在 mark 點(diǎn)之后插入元素,mark 點(diǎn)由其他插入函數(shù)提供 |
| InsertBefore(v interface {}, mark * Element) *Element | 在 mark 點(diǎn)之前插入元素,mark 點(diǎn)由其他插入函數(shù)提供 |
| PushBackList(other *List) | 添加 other 列表元素到尾部 |
| PushFrontList(other *List) | 添加 other 列表元素到頭部 |
從列表中刪除元素
列表插入函數(shù)的返回值會(huì)提供一個(gè) *list.Element 結(jié)構(gòu),這個(gè)結(jié)構(gòu)記錄著列表元素的值以及與其他節(jié)點(diǎn)之間的關(guān)系等信息,從列表中刪除元素時(shí),需要用到這個(gè)結(jié)構(gòu)進(jìn)行快速刪除。
列表操作元素:
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)
} 代碼說(shuō)明如下:
第 6 行,創(chuàng)建列表實(shí)例。
第 9 行,將字符串 canon 插入到列表的尾部。
第 12 行,將數(shù)值 67 添加到列表的頭部。
第 15 行,將字符串 fist 插入到列表的尾部,并將這個(gè)元素的內(nèi)部結(jié)構(gòu)保存到 element 變量中。
第 18 行,使用 element 變量,在 element 的位置后面插入 high 字符串。
第 21 行,使用 element 變量,在 element 的位置前面插入 noon 字符串。
第 24 行,移除 element 變量對(duì)應(yīng)的元素。
下表中展示了每次操作后列表的實(shí)際元素情況。
| 操作內(nèi)容 | 列表元素 |
|---|---|
| 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 |
遍歷列表——訪問(wèn)列表的每一個(gè)元素
遍歷雙鏈表需要配合 Front() 函數(shù)獲取頭元素,遍歷時(shí)只要元素不為空就可以繼續(xù)進(jìn)行,每一次遍歷都會(huì)調(diào)用元素的 Next() 函數(shù),代碼如下所示。
l := list.New()
// 尾部添加
l.PushBack("canon")
// 頭部添加
l.PushFront(67)
for i := l.Front(); i != nil; i = i.Next() {
fmt.Println(i.Value)
}代碼輸出如下:
67
canon
代碼說(shuō)明如下:
- 第 1 行,創(chuàng)建一個(gè)列表實(shí)例。
- 第 4 行,將 canon 放入列表尾部。
- 第 7 行,在隊(duì)列頭部放入 67。
- 第 9 行,使用 for 語(yǔ)句進(jìn)行遍歷,其中 i:=l.Front() 表示初始賦值,只會(huì)在一開(kāi)始執(zhí)行一次,每次循環(huán)會(huì)進(jìn)行一次 i != nil 語(yǔ)句判斷,如果返回 false,表示退出循環(huán),反之則會(huì)執(zhí)行 i = i.Next()。
- 第 10 行,使用遍歷返回的 *list.Element 的 Value 成員取得放入列表時(shí)的原值。
當(dāng)前標(biāo)題:創(chuàng)新互聯(lián)GO教程:Go語(yǔ)言list(列表)
當(dāng)前地址:http://fisionsoft.com.cn/article/ccchjhi.html


咨詢
建站咨詢
