From dc00eb99f3f9dc4d4de01b135d8278736833a59c Mon Sep 17 00:00:00 2001 From: eson <474420502@qq.com> Date: Sun, 28 Apr 2019 02:52:00 +0800 Subject: [PATCH] =?UTF-8?q?hashmap=20=E7=BC=93=E5=AD=98=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hashmap/avlkeydup.go | 24 +++++++++++++++++ hashmap/hashmap.go | 8 +++++- hashmap/pool.go | 61 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 hashmap/pool.go diff --git a/hashmap/avlkeydup.go b/hashmap/avlkeydup.go index fa53109..329ad8c 100644 --- a/hashmap/avlkeydup.go +++ b/hashmap/avlkeydup.go @@ -94,6 +94,30 @@ func (tree *avlTree) Clear() { // return nil, false // } +func (tree *avlTree) Traversal(every func(*avlNode) bool) { + if tree.root == nil { + return + } + + var traverasl func(cur *avlNode) bool + traverasl = func(cur *avlNode) bool { + if cur == nil { + return true + } + if !traverasl(cur.children[0]) { + return false + } + if !every(cur) { + return false + } + if !traverasl(cur.children[1]) { + return false + } + return true + } + traverasl(tree.root) +} + func (tree *avlTree) Get(key interface{}) (interface{}, bool) { n, ok := tree.GetNode(key) if ok { diff --git a/hashmap/hashmap.go b/hashmap/hashmap.go index fccb44d..37a07ee 100644 --- a/hashmap/hashmap.go +++ b/hashmap/hashmap.go @@ -15,6 +15,7 @@ type HashMap struct { GetHash HashCode Compare compare.Compare + pool *nodePool growsize uint size uint } @@ -31,6 +32,7 @@ func New(hcode HashCode, comp compare.Compare) *HashMap { hm.growfactor = 2 hm.GetHash = hcode hm.Compare = comp + hm.pool = newNodePool() // initcap := uint(8) hm.table = newTable() hm.countNextGrow() @@ -83,9 +85,13 @@ func (hm *HashMap) Put(key, value interface{}) { bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) { data[idx] = avlNew(hm.Compare) }) - if bkt.Put(key, value) { + + n := hm.pool.Get() + if bkt.PutNode(n) { hm.size++ hm.grow() + } else { + hm.pool.Recycling(n) } } diff --git a/hashmap/pool.go b/hashmap/pool.go new file mode 100644 index 0000000..64223e0 --- /dev/null +++ b/hashmap/pool.go @@ -0,0 +1,61 @@ +package hashmap + +import ( + "474420502.top/eson/structure/lastack" +) + +type nodePool struct { + cache *lastack.Stack + data []avlNode + size int + growSize int + slimmingSize int +} + +func newNodePool() *nodePool { + p := &nodePool{} + p.cache = lastack.New() + p.data = make([]avlNode, 16, 16) + p.countNextGrow() + return p +} + +func (pool *nodePool) Get() *avlNode { + if !pool.cache.Empty() { + v, _ := pool.cache.Pop() + return v.(*avlNode) + } + pool.Grow() + cur := &pool.data[pool.size] + pool.size++ + return cur +} + +func (pool *nodePool) Recycling(n *avlNode) { + pool.cache.Push(n) +} + +func (pool *nodePool) Grow() { + if pool.size >= len(pool.data) { + growsize := pool.size << 1 + temp := make([]avlNode, growsize, growsize) + copy(temp, pool.data) + pool.data = temp + pool.countNextGrow() + } +} + +func (pool *nodePool) slimming() { + if pool.size <= pool.slimmingSize { + growsize := len(pool.data) - pool.slimmingSize<<1 + temp := make([]avlNode, growsize, growsize) + copy(temp, pool.data) + pool.data = temp + pool.countNextGrow() + } +} + +func (pool *nodePool) countNextGrow() { + pool.growSize = len(pool.data) + pool.slimmingSize = pool.growSize << 1 +}