資料結構——Golang實現單鏈表
轉載請註明出處: 資料結構——Golang實現單鏈表
Golang
1. 單鏈表
1.1. 定義
單向連結串列
(單鏈表)是連結串列的一種,其特點是連結串列的連結方向是單向的,對連結串列的訪問要通過順序讀取從頭部開始;連結串列是使用指標進行構造的列表;又稱為結點列表,因為連結串列是由一個個結點組裝起來的;其中每個結點都有指標成員變數指向列表中的下一個結點;
列表是由結點構成,head指標指向第一個成為表頭結點,而終止於最後一個指向nuLL的指標。
1.2. 優點
- 單個結點建立非常方便,普通的線性記憶體通常在建立的時候就需要設定資料的大小
- 結點的刪除非常方便,不需要像線性結構那樣移動剩下的資料
- 結點的訪問方便,可以通過迴圈或者遞迴的方法訪問到任意資料,但是平均的訪問效率低於線性表。
2. Golang 實現
2.1. 相關結構體
首先需要先定義一下連結串列相關的結果, SingleObject
用於每個節點的資料,為interface{}結構, SingleNode
為連結串列中的節點, SingleList
單鏈表,為了多協程讀寫安全,所以在連結串列中加了讀寫鎖。
具體定義如下:
// 節點資料 type SingleObject interface{} // 單鏈表節點 type SingleNode struct { Data SingleObject Next *SingleNode } // 單鏈表 type SingleList struct{ mutex *sync.RWMutex Head *SingleNode Tail *SingleNode Size uint }
2.2. 連結串列初始化
定義完結構,接下來就需要對單鏈表進行初始化了。程式碼如下:
// 初始化 func (list *SingleList) Init(){ list.Size = 0 list.Head = nil list.Tail = nil list.mutex = new(sync.RWMutex) }
2.3. 新增節點
連結串列節點的新增分為兩種,一種是在連結串列後面追加節點,該方式,我們稱為append;另外一種方式是在指定位置插入節點,我們叫做insert。
另外新增時,若為第一個節點需特殊處理一下。下面請看程式碼:
// 新增節點到連結串列尾部 func (list *SingleList)Append(node *SingleNode) bool { if node == nil{ return false } list.mutex.Lock() defer list.mutex.Unlock() if list.Size == 0{ list.Head = node list.Tail = node list.Size = 1 return true } tail := list.Tail tail.Next = node list.Tail = node list.Size += 1 return true } // 插入節點到指定位置 func (list *SingleList)Insert(index uint, node *SingleNode) bool { if node == nil { return false } if index > list.Size{ return false } list.mutex.Lock() defer list.mutex.Unlock() if index == 0{ node.Next = list.Head list.Head = node list.Size += 1 return true } var i uint ptr := list.Head for i = 1; i < index; i ++ { ptr = ptr.Next } next := ptr.Next ptr.Next = node node.Next = next list.Size += 1 return true }
2.4. 刪除節點
有了新增功能自然就少不了刪除,此外,刪除節點時,如果指定的位置是連結串列的頭部或尾部,都需要特殊處理下。看程式碼:
// 刪除指定位置的節點 func (list *SingleList)Delete(index uint) bool { if list == nil || list.Size == 0 || index > list.Size - 1 { return false } list.mutex.Lock() defer list.mutex.Unlock() if index == 0 { head := list.Head.Next list.Head = head if list.Size == 1{ list.Tail = nil } list.Size -= 1 return true } ptr := list.Head var i uint for i = 1; i < index; i++{ ptr = ptr.Next } next := ptr.Next ptr.Next = next.Next if index == list.Size - 1 { list.Tail = ptr } list.Size -= 1 return true }
2.6. 查詢節點
根據指定的位置索引,查詢出節點內容。
// 獲取指定位置的節點,不存在則返回nil func (list *SingleList)Get(index uint) *SingleNode{ if list == nil || list.Size == 0 || index > list.Size - 1 { return nil } list.mutex.RLock() defer list.mutex.RUnlock() if index == 0{ return list.Head } node := list.Head var i uint for i = 0; i < index; i ++ { node = node.Next } return node }
2.7. 列印連結串列
最後,我們增加一個列印連結串列的功能,方便我們看整個連結串列的內容:
// 輸出連結串列 func (list *SingleList)Display(){ if list == nil { fmt.Println("this single list is nil") return } list.mutex.RLock() defer list.mutex.RUnlock() fmt.Printf("this single list size is %d \n", list.Size) ptr := list.Head var i uint for i = 0; i < list.Size; i++{ fmt.Printf("No%3d data is %v\n", i + 1, ptr.Data) ptr = ptr.Next } }
完
轉載請註明出處: 資料結構——Golang實現單鏈表