Golang 資料結構:鏈表

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Golang 中鏈表的實現及常用操作,資料結構系列原文:flaviocopes.com,翻譯已獲作者授權。

前言

鏈表的結構類似於數組,但插入元素的代價比數組小得多,因為在數組中插入元素,需要把插入位置後邊所有的元素後移一個位置,刪除元素則要全部前移。

數組將元素順序儲存在記憶體單元中(靜態分配記憶體),而鏈表是通過元素中的指標,將元素儲存在零散的記憶體中(動態分配記憶體)

鏈表相比數組有個明顯的缺點:尋找元素時不知道元素在鏈表中的地址,需要從第一個元素開始遍曆整條鏈表來尋找。

鏈表結構

基本操作:
1
2
3
4
5
6
7
8
Append(t)// 將元素 t 追加到鏈表尾部
Insert(i, t) // 在位置 i 處插入元素 t
RemoveAt(i)// 移除位置 i 的元素
IndexOf(t)// 返回元素 t 的位置
IsEmpty(l)// l 是空鏈表則返回 true
Size()// 返回鏈表的長度
String()// 返回鏈表的字串表示
Head()// 返回鏈表的首結點,以便迭代鏈表

我使用 genny 來建立了一個通用的類型: ItemLinkedList,使得鏈表能儲存任意資料類型的元素。這樣能將鏈表的實現和具體儲存的資料分離開,高度封裝了鏈表的實現。

代碼實現
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// linkedlist 包為 Item 類型的元素建立一個 ItemLinkedList 鏈表
package linkedlist

import (
"github.com/cheekybits/genny/generic"
"sync"
"fmt"
)

type Item generic.Type

type Node struct {
content Item
next *Node
}

type ItemLinkedList struct {
head *Node
size int
lock sync.RWMutex
}

// 在鏈表結尾追加元素
func (list *ItemLinkedList) Append(t Item) {
list.lock.Lock()
newNode := Node{t, nil}

// 尋找並追加
if list.head == nil { // 空鏈表第一次追加元素
list.head = &newNode
} else {
curNode := list.head // 遍曆鏈表,找到尾部結點
for {
if curNode.next == nil {
break
}
curNode = curNode.next
}
curNode.next = &newNode
}

// 追加後鏈表長度+1
list.size++
list.lock.Unlock()
}

// 在鏈表指定位置插入指定元素
func (list *ItemLinkedList) Insert(i int, t Item) error {
list.lock.Lock()
defer list.lock.Unlock()
if i < 0 || i > list.size {
return fmt.Errorf("Index %d out of bonuds", i)
}
newNode := Node{t, nil}

if i == 0 { // 插入到鏈表頭部
newNode.next = list.head
list.head = &newNode
list.size++
return nil
}

preNode := list.head
preIndex := 0
for preIndex < i-2 {
preIndex++
preNode = preNode.next
}
// 執行插入
newNode.next = preNode.next
preNode.next = &newNode
list.size++
return nil
}

// 刪除指定位置的元素
func (list *ItemLinkedList) RemoveAt(i int) (*Item, error) {
list.lock.Lock()
defer list.lock.Unlock()

if i < 0 || i > list.size {
return nil, fmt.Errorf("Index %d out of bonuds", i)
}

curNode := list.head
preIndex := 0
for preIndex < i-1 {
preIndex++
curNode = curNode.next
}
item := curNode.content
curNode.next = curNode.next.next
list.size--
return &item, nil
}

// 擷取指定元素在鏈表中的索引
func (list *ItemLinkedList) IndexOf(t Item) int {
list.lock.RLock()
defer list.lock.RUnlock()
curNode := list.head
locIndex := 0
for {
if curNode.content == t {
return locIndex
}
if curNode.next == nil {
return -1
}
curNode = curNode.next
locIndex++
}
}

// 檢查鏈表是否為空白
func (list *ItemLinkedList) IsEmpty() bool {
list.lock.RLock()
defer list.lock.RUnlock()
if list.head == nil {
return true
}
return false
}

// 擷取鏈表的長度
func (list *ItemLinkedList) Size() int {
list.lock.RLock()
defer list.lock.RUnlock()
size := 1
nextNode := list.head
for {
if nextNode == nil || nextNode.next == nil { // 單結點鏈表的 nextNode == nil
break
}
size++
nextNode = nextNode.next
}
return size
}

// 格式化列印鏈表
func (list *ItemLinkedList) String() {
list.lock.RLock()
defer list.lock.RUnlock()
curNode := list.head
for {
if curNode == nil {
break
}
print(curNode.content)
print(" ")
curNode = curNode.next
}
println()
}

// 擷取鏈表的頭結點
func (list *ItemLinkedList) Head() *Node {
list.lock.RLock()
defer list.lock.RUnlock()
return list.head
}
測試案例:linkedlist_test.go

使用

通過 generate 來為鏈表指定元素具體的資料類型,如:

1
2
//generate a `IntLinkedList` linked list of `int` values
genny -in linkedlist.go -out linkedlist_int.go gen "Item=int"

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.