Go實(shí)現(xiàn)List、Set、Stack、Deque等數(shù)據(jù)結(jié)構(gòu)的操作方法
Go實(shí)現(xiàn)List、Set、Stack、Deque等數(shù)據(jù)結(jié)構(gòu)
完整代碼地址(歡迎大家??):
https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-data-structure
大家有接觸過(guò)除Go其他語(yǔ)言(如:Java)可能就會(huì)想為什么Go沒(méi)有像deque、stack、set、list這些常見(jiàn)的數(shù)據(jù)容器。尤其是對(duì)于那些習(xí)慣了用這些容器解決LeetCode問(wèn)題的同學(xué)來(lái)說(shuō),就更為不便。
1 為什么Go原生不提供這些容器:為了簡(jiǎn)潔
Go語(yǔ)言自誕生以來(lái)就有著非常明確的目標(biāo),那就是簡(jiǎn)潔、高效、并發(fā)。為了實(shí)現(xiàn)這些目標(biāo),Go在設(shè)計(jì)上做了很多取舍。
- 簡(jiǎn)單性:Go語(yǔ)言團(tuán)隊(duì)的一個(gè)核心目標(biāo)是保持語(yǔ)言的簡(jiǎn)單性。他們認(rèn)為,如果一個(gè)功能可以用簡(jiǎn)單的組合來(lái)實(shí)現(xiàn),那就沒(méi)有必要把它放進(jìn)標(biāo)準(zhǔn)庫(kù)里。
- deque、stack、set、list這些數(shù)據(jù)結(jié)構(gòu)雖然常用,但它們并不是編寫(xiě)高效、可維護(hù)代碼的唯一途徑。通過(guò)組合切片和映射,開(kāi)發(fā)者可以實(shí)現(xiàn)絕大多數(shù)需要的數(shù)據(jù)結(jié)構(gòu)。
- 鼓勵(lì)最佳實(shí)踐:Go語(yǔ)言推崇一種“最小驚奇”的設(shè)計(jì)原則。也就是說(shuō),代碼應(yīng)該盡可能地容易理解和預(yù)測(cè)。標(biāo)準(zhǔn)庫(kù)的設(shè)計(jì)哲學(xué)之一就是提供最少但足夠的工具,讓開(kāi)發(fā)者能夠按照最佳實(shí)踐來(lái)編寫(xiě)代碼。
- 這個(gè)哲學(xué)避免了標(biāo)準(zhǔn)庫(kù)的膨脹,同時(shí)確保了代碼的清晰性和可維護(hù)性。
- 社區(qū)的力量:Go語(yǔ)言的生態(tài)系統(tǒng)非常活躍,有很多高質(zhì)量的第三方庫(kù)可以提供你需要的高級(jí)數(shù)據(jù)結(jié)構(gòu)。如果標(biāo)準(zhǔn)庫(kù)包含了所有可能需要的數(shù)據(jù)結(jié)構(gòu),那它將變得非常龐大且難以維護(hù)。
相反,通過(guò)社區(qū)貢獻(xiàn),Go可以保持核心的簡(jiǎn)潔,同時(shí)又不失靈活性。
2 實(shí)現(xiàn)
完整代碼地址:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-data-structure
雖然Go語(yǔ)言沒(méi)有內(nèi)置這些高級(jí)數(shù)據(jù)結(jié)構(gòu),但通過(guò)組合使用切片和映射,我們依然可以實(shí)現(xiàn)幾乎所有需要的數(shù)據(jù)結(jié)構(gòu)。
- 而且,這種方式更符合Go語(yǔ)言簡(jiǎn)潔、高效的設(shè)計(jì)哲學(xué)。
- 最重要的是,這也讓我們更加理解這些數(shù)據(jù)結(jié)構(gòu)的內(nèi)部實(shí)現(xiàn),而不僅僅是簡(jiǎn)單地調(diào)用現(xiàn)成的API。
所以,下次再遇到類似的問(wèn)題,大家也可以自己試試看實(shí)現(xiàn)這些數(shù)據(jù)結(jié)構(gòu),既能提升編碼能力,又能更深入地理解Go語(yǔ)言的設(shè)計(jì)理念。
List
思路:對(duì)于列表來(lái)說(shuō),通常需要有Add、Remove等操作,其實(shí)golang原生的切片就很接近切片,因此我們簡(jiǎn)單做封裝即可
package main import ( "errors" "fmt" ) /* List: - NewList(): 創(chuàng)建一個(gè)新的列表 - Add(element): 在列表末尾添加元素 - Remove(index): 根據(jù)索引移除元素 - Size(): 返回列表的大小 - Get(index): 根據(jù)索引獲取元素 - IsEmpty(): 判斷列表是否為空 - Clear(): 清空列表 - GetFirst(): 獲取第一個(gè)元素 - GetLast(): 獲取最后一個(gè)元素 - RemoveLast(): 移除最后一個(gè)元素 - AddFirst(element): 在列表開(kāi)頭添加元素 - RemoveFirst(): 移除第一個(gè)元素 ... */ type List struct { data []interface{} } // NewList 創(chuàng)建一個(gè)新的列表 func NewList() *List { return &List{ data: []interface{}{}, } } // Add 在列表末尾添加元素 func (l *List) Add(v interface{}) { l.data = append(l.data, v) } // Remove 根據(jù)索引移除元素 func (l *List) Remove(index int) error { if index < 0 || index >= len(l.data) { return errors.New("index out of bounds") } l.data = append(l.data[:index], l.data[index+1:]...) return nil } // Size 返回列表的大小 func (l *List) Size() int { return len(l.data) } // Get 根據(jù)索引獲取元素 func (l *List) Get(index int) (interface{}, error) { if index < 0 || index >= len(l.data) { return nil, errors.New("index out of bounds") } return l.data[index], nil } // IsEmpty 判斷列表是否為空 func (l *List) IsEmpty() bool { return len(l.data) == 0 } // Clear 清空列表 func (l *List) Clear() { l.data = []interface{}{} } // GetFirst 獲取第一個(gè)元素 func (l *List) GetFirst() (interface{}, error) { if l.IsEmpty() { return nil, errors.New("list is empty") } return l.data[0], nil } // GetLast 獲取最后一個(gè)元素 func (l *List) GetLast() (interface{}, error) { if l.IsEmpty() { return nil, errors.New("list is empty") } return l.data[len(l.data)-1], nil } // AddFirst 在列表開(kāi)頭添加元素 func (l *List) AddFirst(v interface{}) { l.data = append([]interface{}{v}, l.data...) } // RemoveFirst 移除第一個(gè)元素 func (l *List) RemoveFirst() error { if l.IsEmpty() { return errors.New("list is empty") } l.data = l.data[1:] return nil } // RemoveLast 移除最后一個(gè)元素 func (l *List) RemoveLast() error { if l.IsEmpty() { return errors.New("list is empty") } l.data = l.data[:len(l.data)-1] return nil } func main() { list := NewList() // 測(cè)試 Add 和 Get list.Add(1) list.Add(2) list.Add(3) value, err := list.Get(1) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Value at index 1:", value) // 輸出: Value at index 1: 2 } // 測(cè)試 Remove err = list.Remove(1) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Size after remove:", list.Size()) // 輸出: Size after remove: 2 } // 測(cè)試 GetFirst 和 GetLast first, err := list.GetFirst() if err != nil { fmt.Println("Error:", err) } else { fmt.Println("First element:", first) // 輸出: First element: 1 } last, err := list.GetLast() if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Last element:", last) // 輸出: Last element: 3 } // 測(cè)試 AddFirst 和 RemoveFirst list.AddFirst(0) first, err = list.GetFirst() if err != nil { fmt.Println("Error:", err) } else { fmt.Println("First element after addFirst:", first) // 輸出: First element after addFirst: 0 } err = list.RemoveFirst() if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Size after removeFirst:", list.Size()) // 輸出: Size after removeFirst: 2 } // 測(cè)試 RemoveLast err = list.RemoveLast() if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Size after removeLast:", list.Size()) // 輸出: Size after removeLast: 1 } // 測(cè)試 Clear list.Clear() fmt.Println("Is list empty after clear?", list.IsEmpty()) // 輸出: Is list empty after clear? true }
Stack
Stack最大的特點(diǎn)就是:先進(jìn)后出,這里底層存儲(chǔ)我們也可以采用切片來(lái)進(jìn)行封裝
package main import ( "fmt" ) /* Stack: - Push(item): 入棧 - Pop(): 出棧 - Peek(): 返回棧頂元素,但不刪除它 - IsEmpty(): 判斷棧是否為空 - Search(item): 搜索 item 元素在棧中的位置,如果沒(méi)找到,返回 -1 - Clear(): 清空棧 ... */ type Stack struct { data []interface{} } func NewStack() *Stack { return &Stack{ data: []interface{}{}, } } // Push 入棧 func (s *Stack) Push(v interface{}) { s.data = append(s.data, v) } // Pop 出棧 func (s *Stack) Pop() interface{} { if len(s.data) == 0 { return nil } val := s.data[len(s.data)-1] s.data = s.data[:len(s.data)-1] return val } // Peek 返回棧頂元素,但不刪除它 func (s *Stack) Peek() interface{} { if len(s.data) == 0 { return nil } return s.data[len(s.data)-1] } // IsEmpty 判斷棧是否為空 func (s *Stack) IsEmpty() bool { return len(s.data) == 0 } // Search 搜索 item 元素在棧中的位置,如果沒(méi)找到,返回 -1 func (s *Stack) Search(v interface{}) int { for index, value := range s.data { if value == v { return index } } return -1 } // Clear 清空棧 func (s *Stack) Clear() { s.data = []interface{}{} } func main() { stack := NewStack() // 測(cè)試 Push 和 Peek stack.Push(1) stack.Push(2) stack.Push(3) fmt.Println("Top element:", stack.Peek()) // 輸出: Top element: 3 // 測(cè)試 Pop fmt.Println("Popped element:", stack.Pop()) // 輸出: Popped element: 3 fmt.Println("Top element after pop:", stack.Peek()) // 輸出: Top element after pop: 2 // 測(cè)試 IsEmpty fmt.Println("Is stack empty?", stack.IsEmpty()) // 輸出: Is stack empty? false // 測(cè)試 Search fmt.Println("Index of 2:", stack.Search(2)) // 輸出: Index of 2: 1 fmt.Println("Index of 3:", stack.Search(3)) // 輸出: Index of 3: -1 // 測(cè)試 Clear stack.Clear() fmt.Println("Is stack empty after clear?", stack.IsEmpty()) // 輸出: Is stack empty after clear? true }
Deque
Deque雙端隊(duì)列:前后都可以進(jìn)出
package main import ( "container/list" "fmt" ) /* Deque: - PushFront: 在隊(duì)列前端插入元素 - PushBack: 在隊(duì)列后端插入元素 - PopFront: 從隊(duì)列前端移除并返回元素 - PopBack: 從隊(duì)列后端移除并返回元素 ... */ // Deque 雙端隊(duì)列結(jié)構(gòu)體 type Deque struct { data *list.List } // NewDeque 創(chuàng)建一個(gè)新的雙端隊(duì)列 func NewDeque() *Deque { return &Deque{data: list.New()} } // PushFront 在隊(duì)列前端插入元素 func (d *Deque) PushFront(value interface{}) { d.data.PushFront(value) } // PushBack 在隊(duì)列后端插入元素 func (d *Deque) PushBack(value interface{}) { d.data.PushBack(value) } // PopFront 移除并返回隊(duì)列前端的元素 func (d *Deque) PopFront() interface{} { front := d.data.Front() if front != nil { d.data.Remove(front) return front.Value } return nil } // PopBack 移除并返回隊(duì)列后端的元素 func (d *Deque) PopBack() interface{} { back := d.data.Back() if back != nil { d.data.Remove(back) return back.Value } return nil } func main() { deque := NewDeque() // 測(cè)試 PushFront 和 PushBack deque.PushBack(1) deque.PushFront(2) deque.PushBack(3) deque.PushFront(4) // 測(cè)試 PopFront fmt.Println("Popped from front:", deque.PopFront()) // 輸出: Popped from front: 4 fmt.Println("Popped from front:", deque.PopFront()) // 輸出: Popped from front: 2 // 測(cè)試 PopBack fmt.Println("Popped from back:", deque.PopBack()) // 輸出: Popped from back: 3 fmt.Println("Popped from back:", deque.PopBack()) // 輸出: Popped from back: 1 // 測(cè)試空隊(duì)列的情況 fmt.Println("Popped from front on empty deque:", deque.PopFront()) // 輸出: Popped from front on empty deque: <nil> fmt.Println("Popped from back on empty deque:", deque.PopBack()) // 輸出: Popped from back on empty deque: <nil> // 再次測(cè)試 PushFront 和 PushBack deque.PushFront(5) deque.PushBack(6) // 測(cè)試 PeekFront 和 PeekBack fmt.Println("Front element:", deque.PopFront()) // 輸出: Front element: 5 fmt.Println("Back element:", deque.PopBack()) // 輸出: Back element: 6 }
Set
package main import ( "fmt" "sync" ) /* Set: 可以去除重復(fù)元素 - Add: 添加元素 - Remove: 刪除元素 - Contains: 檢查元素是否存在 - IsEmpty: 判斷集合是否為空 - Clear: 清空集合 - Iterator: 返回一個(gè)迭代器通道 ... */ type Set struct { mu sync.RWMutex data map[interface{}]bool } // NewSet 創(chuàng)建一個(gè)新的集合 func NewSet() *Set { return &Set{ data: make(map[interface{}]bool), } } // Add 添加元素到集合 func (s *Set) Add(value interface{}) { s.mu.Lock() defer s.mu.Unlock() s.data[value] = true } // Remove 從集合中刪除元素 func (s *Set) Remove(value interface{}) { s.mu.Lock() defer s.mu.Unlock() delete(s.data, value) } // Contains 檢查元素是否存在于集合中 func (s *Set) Contains(value interface{}) bool { s.mu.RLock() defer s.mu.RUnlock() return s.data[value] } // IsEmpty 判斷集合是否為空 func (s *Set) IsEmpty() bool { s.mu.RLock() defer s.mu.RUnlock() return len(s.data) == 0 } // Clear 清空集合 func (s *Set) Clear() { s.mu.Lock() defer s.mu.Unlock() s.data = make(map[interface{}]bool) } // Iterator 返回一個(gè)迭代器通道 func (s *Set) Iterator() <-chan interface{} { ch := make(chan interface{}) go func() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered in Iterator:", r) } close(ch) }() s.mu.RLock() defer s.mu.RUnlock() for k := range s.data { ch <- k } }() return ch } func main() { set := NewSet() // 測(cè)試 Add 和 Contains set.Add(1) set.Add(2) set.Add(3) fmt.Println("Contains 1:", set.Contains(1)) // 輸出: Contains 1: true fmt.Println("Contains 4:", set.Contains(4)) // 輸出: Contains 4: false // 測(cè)試 Remove set.Remove(2) fmt.Println("Contains 2 after remove:", set.Contains(2)) // 輸出: Contains 2 after remove: false // 測(cè)試 IsEmpty fmt.Println("Is set empty?", set.IsEmpty()) // 輸出: Is set empty? false // 測(cè)試 Clear set.Clear() fmt.Println("Is set empty after clear?", set.IsEmpty()) // 輸出: Is set empty after clear? true // 測(cè)試 Iterator set.Add(1) set.Add(2) set.Add(3) fmt.Println("Elements in set:") for i := range set.Iterator() { fmt.Println(i) } // 其他測(cè)試代碼 data := make([]int, 2, 20) data[0] = -1 fmt.Println("Length of data:", len(data)) // 輸出: Length of data: 2 fmt.Println("Capacity of data:", cap(data)) // 輸出: Capacity of data: 20 }
更多的數(shù)據(jù)結(jié)構(gòu),比如LinkedList等,大家可以自行下來(lái)嘗試一下。
3 代碼地址
完整代碼地址(歡迎大家??):
https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-data-structure
到此這篇關(guān)于Go實(shí)現(xiàn)List、Set、Stack、Deque等數(shù)據(jù)結(jié)構(gòu)的文章就介紹到這了,更多相關(guān)Go List、Set、Stack、Deque數(shù)據(jù)結(jié)構(gòu)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 淺析Go語(yǔ)言中的map數(shù)據(jù)結(jié)構(gòu)是如何實(shí)現(xiàn)的
- Golang對(duì)struct字段重新排序優(yōu)化數(shù)據(jù)結(jié)構(gòu)性能實(shí)踐
- Go數(shù)據(jù)結(jié)構(gòu)之HeapMap實(shí)現(xiàn)指定Key刪除堆
- Golang實(shí)現(xiàn)數(shù)據(jù)結(jié)構(gòu)Stack(堆棧)的示例詳解
- Golang迭代如何在Go中循環(huán)數(shù)據(jù)結(jié)構(gòu)使用詳解
- 詳解如何在Go語(yǔ)言中循環(huán)數(shù)據(jù)結(jié)構(gòu)
- Go語(yǔ)言數(shù)據(jù)結(jié)構(gòu)之二叉樹(shù)可視化詳解
- Go 數(shù)據(jù)結(jié)構(gòu)之堆排序示例詳解
相關(guān)文章
Golang 實(shí)現(xiàn)Socket服務(wù)端和客戶端使用TCP協(xié)議通訊
這篇文章主要介紹了Golang 實(shí)現(xiàn)Socket服務(wù)端和客戶端使用TCP協(xié)議通訊,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12Go位集合相關(guān)操作bitset庫(kù)安裝使用
這篇文章主要為大家介紹了Go位集合相關(guān)操作bitset庫(kù)安裝使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Golang實(shí)現(xiàn)http重定向https
這篇文章介紹了Golang實(shí)現(xiàn)http重定向https的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07Golang實(shí)現(xiàn)SSH、SFTP操作小結(jié)
在日常的一些開(kāi)發(fā)場(chǎng)景中,我們需要去和遠(yuǎn)程服務(wù)器進(jìn)行一些通信,本文主要介紹了Golang實(shí)現(xiàn)SSH、SFTP操作小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04Golang收支記賬程序詳細(xì)編寫(xiě)過(guò)程
這篇文章主要介紹了Golang實(shí)現(xiàn)收支記賬程序流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換
在軟件開(kāi)發(fā)的世界里,數(shù)據(jù)類型轉(zhuǎn)換是一項(xiàng)基礎(chǔ)而重要的技能,尤其在Go語(yǔ)言這樣類型嚴(yán)格的語(yǔ)言中,正確高效地進(jìn)行類型轉(zhuǎn)換對(duì)于性能優(yōu)化和代碼質(zhì)量至關(guān)重要,本文給大家介紹了Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換,需要的朋友可以參考下2024-02-02golang 實(shí)用庫(kù)gotable的具體使用
使用gotable框架以實(shí)現(xiàn)在CLI命令行界面中打印表格。本文就介紹一下golang 實(shí)用庫(kù)gotable的使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07