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