From db935ea11f45745f072e7fedd30dcbca5bc12a83 Mon Sep 17 00:00:00 2001 From: eson <474420502@qq.com> Date: Tue, 7 May 2019 13:59:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=87=86=E5=A4=87=E5=9B=9E=E6=BB=9A=E5=88=B0?= =?UTF-8?q?=E6=95=B0=E7=BB=84=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hashmap/bucket.go | 6 ++- hashmap/{hashmap2 => gomap/hashmap.go} | 2 +- hashmap/hashmap.go | 55 +++++++++++++++----------- hashmap/hashmap_test.go | 8 ++-- hashmap/table.go | 24 +++++++---- 5 files changed, 56 insertions(+), 39 deletions(-) rename hashmap/{hashmap2 => gomap/hashmap.go} (98%) diff --git a/hashmap/bucket.go b/hashmap/bucket.go index 5c58eb2..8645670 100644 --- a/hashmap/bucket.go +++ b/hashmap/bucket.go @@ -40,16 +40,17 @@ func (bkt *hmBucket) Add(hash uint, k, v interface{}, Compare compare.Compare) { } } - bkt.size++ if bkt.size < uint(len(bkt.data)) { n := bkt.data[bkt.size] n.hash = hash n.key = k n.value = v + bkt.size++ return } bkt.data = append(bkt.data, &bucketNode{key: k, value: v, hash: hash}) + bkt.size++ } func (bkt *hmBucket) AddNode(node *bucketNode, Compare compare.Compare) { @@ -65,10 +66,11 @@ func (bkt *hmBucket) AddNode(node *bucketNode, Compare compare.Compare) { } } - bkt.size++ if bkt.size < uint(len(bkt.data)) { bkt.data[bkt.size] = node + bkt.size++ return } bkt.data = append(bkt.data, node) + bkt.size++ } diff --git a/hashmap/hashmap2 b/hashmap/gomap/hashmap.go similarity index 98% rename from hashmap/hashmap2 rename to hashmap/gomap/hashmap.go index 56cd19f..438fe84 100644 --- a/hashmap/hashmap2 +++ b/hashmap/gomap/hashmap.go @@ -1,4 +1,4 @@ -package hashmap +package gomap import "fmt" diff --git a/hashmap/hashmap.go b/hashmap/hashmap.go index 3567850..aa8dbde 100644 --- a/hashmap/hashmap.go +++ b/hashmap/hashmap.go @@ -12,8 +12,9 @@ type HashMap struct { table *Table - GetHash HashCode - Compare compare.Compare + GetHash HashCode + Compare compare.Compare + growsize uint size uint } @@ -40,33 +41,34 @@ func (hm *HashMap) countNextGrow() { hm.growsize = hm.table.Cap() << 1 } -var growcount = 0 - func (hm *HashMap) grow() { if hm.size >= hm.growsize { - newsize := hm.size << 1 // newtable := make([]*avlTree, newsize, newsize) hm.table.Grow(int(newsize - hm.size)) - nodelist := make([]*bucketNode, hm.size, hm.size) - - var count = 0 - for i := 0; i < len(hm.table.data); i++ { - curbkt := hm.table.data[i] - tnodelist := curbkt.data - for _, n := range tnodelist { - nodelist[count] = n - count++ + nodelist := make([]*avlNode, hm.size, hm.size) + i := 0 + hm.table.Traversal(func(cur *avlTree) { + if cur != nil { + cur.Traversal(func(node *avlNode) bool { + nodelist[i] = node + i++ + return true + }) + cur.Clear() } - curbkt.size = 0 - } + }) + var hash, index uint for _, node := range nodelist { - index := node.hash % hm.table.cap + hash = hm.GetHash(node.key) + index = hash % hm.table.cap //bkt := newtable[index] - hm.table.data[index].AddNode(node, hm.Compare) - // bkt.data - // bkt.PutNode(node) + bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) { + data[idx] = avlNew(hm.Compare) + }) + node.clearAttr() + bkt.PutNode(node) } hm.countNextGrow() @@ -74,13 +76,18 @@ func (hm *HashMap) grow() { } func (hm *HashMap) Put(key, value interface{}) { - hash := hm.GetHash(key) + tlen := hm.table.Cap() index := hash % tlen - bkt := hm.table.GetWithNilSet(index) - bkt.Add(hash, key, value, hm.Compare) + bkt := hm.table.GetWithNilSet(index, func(data []*avlTree, idx uint) { + data[idx] = avlNew(hm.Compare) + }) + if bkt.Put(key, value) { + hm.size++ + hm.grow() + } } func (hm *HashMap) Get(key interface{}) (interface{}, bool) { @@ -91,7 +98,7 @@ func (hm *HashMap) Get(key interface{}) (interface{}, bool) { bkt := hm.table.Get(index) if bkt != nil { - return bkt.Get(key, hm.Compare), true + return bkt.Get(key) } return nil, false } diff --git a/hashmap/hashmap_test.go b/hashmap/hashmap_test.go index b9e42cf..f206242 100644 --- a/hashmap/hashmap_test.go +++ b/hashmap/hashmap_test.go @@ -26,11 +26,9 @@ func loadTestData() []int { } func TestCount(t *testing.T) { hm := New(HashInt, compare.Int) - - for i := 0; i < 100000; i++ { - hm.Put(i, i) - } - + // for i := 0; i < 100000; i++ { + // hm.Put(i, i) + // } for i := 0; i < 100000; i++ { hm.Put(i, i) } diff --git a/hashmap/table.go b/hashmap/table.go index 493ebf0..3944ca2 100644 --- a/hashmap/table.go +++ b/hashmap/table.go @@ -8,13 +8,13 @@ type Table struct { size uint growsize uint - data []hmBucket + data []*avlTree cap uint } func newTable() *Table { table := &Table{} - table.data = make([]hmBucket, 16, 16) + table.data = make([]*avlTree, 16, 16) table.countCap() return table } @@ -27,20 +27,30 @@ func (t *Table) Cap() uint { return t.cap } +func (t *Table) Traversal(every func(node *avlTree)) { + for _, z := range t.data { + every(z) + } +} + func (t *Table) Grow(size int) { zsize := len(t.data) + size - temp := make([]hmBucket, zsize, zsize) + temp := make([]*avlTree, zsize, zsize) copy(temp, t.data) t.data = temp t.countCap() } -func (t *Table) Get(idx uint) *hmBucket { - return &(t.data[idx]) +func (t *Table) Get(idx uint) *avlTree { + return t.data[idx] } -func (t *Table) GetWithNilSet(idx uint) *hmBucket { - return &(t.data[idx]) +func (t *Table) GetWithNilSet(idx uint, DoSetValue func([]*avlTree, uint)) *avlTree { + + if t.data[idx] == nil { + DoSetValue(t.data, idx) + } + return t.data[idx] } // func (arr *Table) Get(idx int) (interface{}, bool) {