项目作者: hunterhug

项目描述 :
🌲Map implement: Black-Red Tree, AVL Tree
高级语言: Go
项目地址: git://github.com/hunterhug/gomap.git
创建时间: 2020-05-27T01:33:23Z
项目社区:https://github.com/hunterhug/gomap

开源协议:

下载


Map Golang implement by Red-Black Tree, AVL Tree

GitHub forks
GitHub stars
GitHub last commit
GitHub issues

中文说明

Map implement by tree data struct such Red-Black Tree, AVL Tree.

Our tree map is design to be concurrent safe, and don’t waste any space different from golang standard map which not shrink even map key pairs num is 0.

Usage

Simple get it by:

  1. go get -v github.com/hunterhug/gomap

There are:

  1. Standard Red-Black Tree Map(2-3-4-Tree): gomap.New()gomap.NewMap(),gomap.NewRBMap().
  2. AVL Tree Map: gomap.NewAVLMap().

Core api:

  1. // Map method
  2. // design to be concurrent safe
  3. type Map interface {
  4. Put(key string, value interface{}) // put key pairs
  5. Delete(key string) // delete a key
  6. Get(key string) (value interface{}, exist bool) // get value from key
  7. GetInt(key string) (value int, exist bool, err error) // get value auto change to Int
  8. GetInt64(key string) (value int64, exist bool, err error) // get value auto change to Int64
  9. GetString(key string) (value string, exist bool, err error) // get value auto change to string
  10. GetFloat64(key string) (value float64, exist bool, err error) // get value auto change to string
  11. GetBytes(key string) (value []byte, exist bool, err error) // get value auto change to []byte
  12. Contains(key string) (exist bool) // map contains key?
  13. Len() int64 // map key pairs num
  14. KeyList() []string // map key out to list from top to bottom which is layer order
  15. KeySortedList() []string // map key out to list sorted
  16. Iterator() MapIterator // map iterator, iterator from top to bottom which is layer order
  17. MaxKey() (key string, value interface{}, exist bool) // find max key pairs
  18. MinKey() (key string, value interface{}, exist bool) // find min key pairs
  19. SetComparator(comparator) Map // set compare func to control key compare
  20. }
  21. // Iterator concurrent not safe
  22. // you should deal by yourself
  23. type MapIterator interface {
  24. HasNext() bool
  25. Next() (key string, value interface{})
  26. }

We has already implement them by non recursion way and optimized a lot, so use which type of tree map is no different.

Example

Some example below:

  1. package main
  2. import (
  3. "fmt"
  4. "github.com/hunterhug/gomap"
  5. "math/rand"
  6. "strconv"
  7. "time"
  8. )
  9. // loop times
  10. // 循环的次数,用于随机添加和删除键值对
  11. // 可以修改成1000
  12. var num = 20
  13. func init() {
  14. // random seed
  15. // 随机数种子初始化
  16. rand.Seed(time.Now().Unix())
  17. }
  18. // diy comparator
  19. // 内部是按键字符串来做查找树,我们把他变成整形
  20. func comparatorInt(key1, key2 string) int64 {
  21. k1, _ := strconv.Atoi(key1)
  22. k2, _ := strconv.Atoi(key2)
  23. if k1 == k2 {
  24. return 0
  25. } else if k1 > k2 {
  26. return 1
  27. } else {
  28. return -1
  29. }
  30. }
  31. func main() {
  32. checkMap := make(map[string]struct{})
  33. // 1. new a map default is rb tree
  34. // 1. 新建一个 Map,默认为标准红黑树实现
  35. m := gomap.New()
  36. //m = gomap.NewAVLMap() // avl tree better version
  37. //m = gomap.NewAVLRecursionMap() // avl tree bad version
  38. m.SetComparator(comparatorInt) // set inner comparator
  39. for i := 0; i < num; i++ {
  40. key := fmt.Sprintf("%d", rand.Int63n(int64(num)))
  41. fmt.Println("add key:", key)
  42. checkMap[key] = struct{}{}
  43. // 2. put key pairs
  44. // 2. 放键值对
  45. m.Put(key, key)
  46. }
  47. fmt.Println("map len is ", m.Len())
  48. // 3. can iterator
  49. // 3. 迭代器使用
  50. iterator := m.Iterator()
  51. for iterator.HasNext() {
  52. k, v := iterator.Next()
  53. fmt.Printf("Iterator key:%s,value %v\n", k, v)
  54. }
  55. // 4. get key
  56. // 4. 获取键中的值
  57. key := "9"
  58. value, exist := m.Get(key)
  59. if exist {
  60. fmt.Printf("%s exist, value is:%s\n", key, value)
  61. } else {
  62. fmt.Printf("%s not exist\n", key)
  63. }
  64. // 5. get int will err
  65. // 5. 获取键中的值,并且指定类型,因为类型是字符串,所以转成整形会报错
  66. _, _, err := m.GetInt(key)
  67. if err != nil {
  68. fmt.Println(err.Error())
  69. }
  70. // 6. check is a rb tree
  71. // 6. 内部辅助,检查是不是一颗正常的红黑树
  72. if m.Check() {
  73. fmt.Println("is a rb tree,len:", m.Len())
  74. }
  75. // 7. delete '9' then find '9'
  76. // 7. 删除键 '9' 然后再找 '9'
  77. m.Delete(key)
  78. value, exist = m.Get(key)
  79. if exist {
  80. fmt.Printf("%s exist, value is:%s\n", key, value)
  81. } else {
  82. fmt.Printf("%s not exist\n", key)
  83. }
  84. // 8. key list
  85. // 8. 获取键列表
  86. fmt.Printf("keyList:%#v,len:%d\n", m.KeyList(), m.Len())
  87. fmt.Printf("keySortList:%#v,len:%d\n", m.KeySortedList(), m.Len())
  88. // 9. delete many
  89. // 9. 删除很多键值对
  90. for key := range checkMap {
  91. v, ok := m.Get(key)
  92. fmt.Printf("find %s:%v=%v, delete key:%s\n", key, v, ok, key)
  93. m.Delete(key)
  94. if !m.Check() {
  95. fmt.Println("is not a rb tree,len:", m.Len())
  96. }
  97. }
  98. // 10. key list
  99. // 10. 获取键列表
  100. fmt.Printf("keyList:%#v,len:%d\n", m.KeyList(), m.Len())
  101. fmt.Printf("keySortList:%#v,len:%d\n", m.KeySortedList(), m.Len())
  102. // 11. check is a rb tree
  103. // 11. 再次检查是否是一颗正常的红黑树
  104. if m.Check() {
  105. fmt.Println("is a rb tree,len:", m.Len())
  106. }
  107. }

BenchTest

We test Golang map and Red-Black Tree, AVL Tree:

  1. go test -run="bench_test.go" -test.bench=".*" -test.benchmem=1 -count=1 master
  2. goos: darwin
  3. goarch: amd64
  4. pkg: github.com/hunterhug/gomap
  5. BenchmarkGolangMapPut-12 1791264 621 ns/op 112 B/op 6 allocs/op
  6. BenchmarkRBTMapPut-12 1000000 1408 ns/op 104 B/op 6 allocs/op
  7. BenchmarkAVLMapPut-12 1000000 1440 ns/op 104 B/op 6 allocs/op
  8. BenchmarkAVLRecursionMapPut-12 1000000 2024 ns/op 104 B/op 6 allocs/op
  9. BenchmarkGolangMapDelete-12 3577232 303 ns/op 15 B/op 1 allocs/op
  10. BenchmarkRBTMapDelete-12 996924 1248 ns/op 15 B/op 1 allocs/op
  11. BenchmarkAVLMapDelete-12 1000000 1227 ns/op 15 B/op 1 allocs/op
  12. BenchmarkAVLRecursionMapDelete-12 667242 1866 ns/op 15 B/op 1 allocs/op
  13. BenchmarkGolangMapGet-12 15797131 72.2 ns/op 2 B/op 1 allocs/op
  14. BenchmarkRBTMapGet-12 5798295 195 ns/op 2 B/op 1 allocs/op
  15. BenchmarkAVLMapGet-12 5831353 197 ns/op 2 B/op 1 allocs/op
  16. BenchmarkAVLRecursionMapGet-12 5275490 228 ns/op 2 B/op 1 allocs/op
  17. BenchmarkGolangMapRandom-12 1256779 940 ns/op 146 B/op 8 allocs/op
  18. BenchmarkRBTMapRandom-12 965804 2652 ns/op 126 B/op 8 allocs/op
  19. BenchmarkAVLMapRandom-12 902004 2805 ns/op 126 B/op 8 allocs/op
  20. BenchmarkAVLRecursionMapRandom-12 701880 3309 ns/op 129 B/op 8 allocs/op
  21. PASS
  22. ok github.com/hunterhug/gomap 66.006s

If you want to save memory space, you can choose our tree map.

License

  1. Copyright [2019-2021] [github.com/hunterhug]
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.