這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Go Map介紹
Go 中 Map是一種無序的索引值對的集合。Map最重要的一點是通過key來快速檢索資料,key類似於索引,指向資料的值。Map是一種集合,所以我們可以像迭代數組和切片那樣迭代它。不過,Map是無序的,我們無法決定它的返回順序,這是因為Map是使用鏈式hash表來實現的。
c++中的實現
在C++ STL 中map 採用紅/黑樹狀結構實現,可以實現有序的Map.
Go 中實現
實現原理
這個實現方法的主要的方法是用空間換取時間。通過list 和 map 兩種資料結構,儲存相同的一份資料。list 用來做順序遍曆,map 用來做尋找,刪除操作
實現代碼
package mainimport ( "container/list" "fmt")type Keyer interface { GetKey() string}type MapList struct { dataMap map[string]*list.Element dataList *list.List}func NewMapList() *MapList { return &MapList{ dataMap: make(map[string]*list.Element), dataList: list.New(), }}func (mapList *MapList) Exists(data Keyer) bool { _, exists := mapList.dataMap[string(data.GetKey())] return exists}func (mapList *MapList) Push(data Keyer) bool { if mapList.Exists(data) { return false } elem := mapList.dataList.PushBack(data) mapList.dataMap[data.GetKey()] = elem return true}func (mapList *MapList) Remove(data Keyer) { if !mapList.Exists(data) { return } mapList.dataList.Remove(mapList.dataMap[data.GetKey()]) delete(mapList.dataMap, data.GetKey())}func (mapList *MapList) Size() int { return mapList.dataList.Len()}func (mapList *MapList) Walk(cb func(data Keyer)) { for elem := mapList.dataList.Front(); elem != nil; elem = elem.Next() { cb(elem.Value.(Keyer)) }}type Elements struct { value string}func (e Elements) GetKey() string { return e.value}func main() { fmt.Println("Starting test...") ml := NewMapList() var a, b, c Keyer a = &Elements{"Alice"} b = &Elements{"Bob"} c = &Elements{"Conrad"} ml.Push(a) ml.Push(b) ml.Push(c) cb := func(data Keyer) { fmt.Println(ml.dataMap[data.GetKey()].Value.(*Elements).value) } fmt.Println("Print elements in the order of pushing:") ml.Walk(cb) fmt.Printf("Size of MapList: %d \n", ml.Size()) ml.Remove(b) fmt.Println("After removing b:") ml.Walk(cb) fmt.Printf("Size of MapList: %d \n", ml.Size())}
優點
紅/黑樹狀結構的插入、刪除、尋找的複雜度都是 O(logn), 而這個實現插入尋找刪除的複雜度都是 O(1), 可以說是一種非常好的資料結構。
缺點
使用了兩個資料結構,空間佔用稍微大了一點。但是和樹的實現比,這個佔用也不算非常大