Go 中的單鍊錶實現
嘿,DEV.to 社群!
這是我的資料結構和演算法系列的一部分。在本文中,我們將實作單鍊錶,然後在本系列的下一篇文章中,我將使用 Go 實作其他類型的鍊錶。
要實作單鍊錶,我們需要結構、節點和單鍊錶本身。但在開始編碼之前,我喜歡這樣組織我的程式碼:
project ├── singly_linked_list │ ├── node.go │ └── list.go └── main.go
節點
節點僅以其最簡單的形式保存資料和指向下一個節點的指標。因此,這是我們將用作節點的結構(在 node.go 檔案中):
type SinglyNode struct { data interface{} next *SinglyNode }
我們使用 interface{} 作為結構中資料的資料類型,因此我們可以在節點內儲存我們想要的任何資料。
然後我們應該定義一些方法來利用我們剛剛建立的節點結構。
func NewSinglyNode(data interface{}) *SinglyNode { return &SinglyNode{data: data} }
如果您習慣了物件導向語言,您很可能會熟悉建構函式是什麼。由於 Go 不是物件導向的語言,因此沒有類,但根據 Go 世界的一些約定,我們通常會建立一個以 New 一詞為前綴的函數。但請記住,在 OOP 語言中 new 是一個特殊的關鍵字,意味著建立一個物件。這裡的 New 只是一個名稱前綴,僅此而已。
NewSinglyNode 函數只接收一個名為 data 的介面{}類型的參數,並傳回一個 SinglyNode 的指標。
接下來,我們為節點定義一些 getter 和 setter:
func (n *SinglyNode) SetData(data interface{}) { n.data = data } func (n *SinglyNode) SetNext(next *SinglyNode) { n.next = next } func (n *SinglyNode) GetData() interface{} { return n.data } func (n *SinglyNode) GetNext() (*SinglyNode, error) { if n.next == nil { return nil, errors.New("no next node") } return n.next, nil }
SetData、Setnext 和 GetData 幾乎是不言自明的。 GetNext 傳回兩個值,一個指向下一個 SinglyNode 的指針,如果沒有下一個節點,則傳回一個錯誤。
這是我總是喜歡添加的額外函數,這樣我總是可以知道我的結構的字串表示形式是:
func (n *SinglyNode) ToString() string { return n.data.(string) }
清單
現在我們已經完成了節點,我們應該實作列表本身。單鍊錶將第一個節點作為頭,而根據我自己的喜好,另外兩個名為「最後」的資料保存最後一個節點,以及一個國家屬性,該屬性保存添加到列表中的節點的計數。
這是 list.go 檔案的第一行:
type SinglyLinkedList struct { head *SinglyNode last *SinglyNode count int }
顯然,一個類似建構子的函式可以輕鬆地建立 SinglyLinkedList:
func NewSinglyLinkedList() *SinglyLinkedList { return &SinglyLinkedList{} }
鍊錶中最重要的函數是新增節點。這是我對這樣一個函數的實作:
func (l *SinglyLinkedList) AttachNode(node *SinglyNode) { if l.head == nil { l.head = node } else { l.last.SetNext(node) } l.last = node l.count++ }
函數的作用如下:
- 檢查鍊錶頭是否為空,如果為空則將接收到的節點設定為鍊錶頭。
- 如果頭不為空,則將接收到的節點設定為最後一個節點的下一個屬性。
- 無論之前發生了什麼,當前節點都應該是最後一個節點,因此下次新增節點時,它可以設定為清單中最後一個節點的下一個節點。
- 將計數加一。
這是一個接收資料並建立節點並將其傳遞給 AttachNode 函數的函數:
func (l *SinglyLinkedList) Add(data interface{}) { l.AttachNode(NewSinglyNode(data)) }
雖然這個功能可能看起來多餘,但它可以輕鬆地將節點添加到列表中,而無需每次手動創建一個。
取得計數屬性的函數:
func (l *SinglyLinkedList) Count() int { return l.count }
最後需要的函數應該會傳回鍊錶中的下一個節點:
func (l *SinglyLinkedList) GetNext() (*SinglyNode, error) { if l.head == nil { return nil, errors.New("list is empty") } return l.head, nil }
我更喜歡將此函數命名為與為節點定義的 GetNext 函數相同的名稱。這樣做是為了提高一致性。當第一次存取鍊錶時,類型是鍊錶,因此無法存取為節點定義的函數。定義一個具有相同名稱的函數將使您能夠盡可能地使用 GetNext 來遍歷清單。
我總是傾向於添加的一個額外函數是透過索引檢索節點的函數:
func (l *SinglyLinkedList) GetByIndex(index int) (*SinglyNode, error) { if l.head == nil { return nil, errors.New("list is empty") } if index+1 > l.count { return nil, errors.New("index out of range") } node, _ := l.GetNext() for i := 0; i < index; i++ { node, _ = node.GetNext() } return node, nil }
函數的作用如下:
- 檢查頭部是否為空回傳錯誤
- 檢查索引 1 是否大於清單的計數以傳回錯誤。我們檢查索引 1 而不是索引,因為我們認為索引從 0 開始就像陣列一樣。
- 將l.GetNext() 指派給名為node 的變數(忽略帶有_ 的錯誤),然後循環查找比提供的索引少的一個,因為我們已經將第一個節點儲存在節點變數中,分配目前節點的下一個節點節點再次成為節點。
- 傳回沒有錯誤的遍歷節點。
測試
現在我們有了鍊錶和節點定義,我們可以在 main.go 檔案中測試它,如下所示:
func main() { list := singly_linked_list.NewSinglyLinkedList() list.Add("One") list.Add("Two") list.Add("Three") firstNode, err := list.GetNext() if err != nil { panic(err) } secondNode, err := firstNode.GetNext() if err != nil { panic(err) } thirdNode, err := secondNode.GetNext() if err != nil { panic(err) } println(firstNode.ToString()) // One println(secondNode.ToString()) // Two println(thirdNode.ToString()) // Three }
或使用 GetByIndex 函數:
func main() { list := singly_linked_list.NewSinglyLinkedList() list.Add("One") list.Add("Two") list.Add("Three") node, err := list.GetByIndex(2) if err != nil { panic(err) } fmt.Println(node.ToString()) // Three }
順便說一下!在這裡查看我的免費 Node.js Essentials 電子書:

NodeJS 重點 |免費電子書
Adnan Babakan(他/他) ・ 2020 年 9 月 11 日
如果您有任何問題或建議,請隨時與我聯繫。
以上是Go 中的單鍊錶實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Go語言在構建高效且可擴展的系統中表現出色,其優勢包括:1.高性能:編譯成機器碼,運行速度快;2.並發編程:通過goroutines和channels簡化多任務處理;3.簡潔性:語法簡潔,降低學習和維護成本;4.跨平台:支持跨平台編譯,方便部署。

Golang在並發性上優於C ,而C 在原始速度上優於Golang。 1)Golang通過goroutine和channel實現高效並發,適合處理大量並發任務。 2)C 通過編譯器優化和標準庫,提供接近硬件的高性能,適合需要極致優化的應用。

Golang和Python各有优势:Golang适合高性能和并发编程,Python适用于数据科学和Web开发。Golang以其并发模型和高效性能著称,Python则以简洁语法和丰富库生态系统著称。

Golang在性能和可擴展性方面優於Python。 1)Golang的編譯型特性和高效並發模型使其在高並發場景下表現出色。 2)Python作為解釋型語言,執行速度較慢,但通過工具如Cython可優化性能。

Golang和C 在性能競賽中的表現各有優勢:1)Golang適合高並發和快速開發,2)C 提供更高性能和細粒度控制。選擇應基於項目需求和團隊技術棧。

C 更適合需要直接控制硬件資源和高性能優化的場景,而Golang更適合需要快速開發和高並發處理的場景。 1.C 的優勢在於其接近硬件的特性和高度的優化能力,適合遊戲開發等高性能需求。 2.Golang的優勢在於其簡潔的語法和天然的並發支持,適合高並發服務開發。

goimpactsdevelopmentpositationality throughspeed,效率和模擬性。 1)速度:gocompilesquicklyandrunseff,IdealforlargeProjects.2)效率:效率:ITScomprehenSevestAndardArdardArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdArdEcceSteral Depentencies,增強的Depleflovelmentimency.3)簡單性。

Golang和C 在性能上的差異主要體現在內存管理、編譯優化和運行時效率等方面。 1)Golang的垃圾回收機制方便但可能影響性能,2)C 的手動內存管理和編譯器優化在遞歸計算中表現更為高效。
