structure/hashmap/hashmap.go

176 lines
3.1 KiB
Go
Raw Normal View History

2019-04-16 19:22:07 +00:00
package hashmap
import (
2019-04-18 01:39:44 +00:00
"474420502.top/eson/structure/compare"
2019-04-16 19:22:07 +00:00
)
2019-04-18 01:39:44 +00:00
type HashCode func(key interface{}) uint
2019-04-16 19:22:07 +00:00
type HashMap struct {
2019-04-21 05:31:39 +00:00
growfactor uint
slimmingfactor uint
2019-04-21 20:46:07 +00:00
table []*avlTree
2019-04-16 19:22:07 +00:00
2019-04-18 01:39:44 +00:00
GetHash HashCode
Compare compare.Compare
2019-04-21 05:31:39 +00:00
growsize uint
size uint
2019-04-18 01:39:44 +00:00
}
type bNode struct {
Next *bNode
Key, Value interface{}
2019-04-16 19:22:07 +00:00
}
type Bucket struct {
2019-04-18 01:39:44 +00:00
size uint
head *bNode
2019-04-16 19:22:07 +00:00
}
func HashInt(key interface{}) uint {
thekey := uint(key.(int))
hbit := thekey & 0xffffffff
lbit := (thekey & 0xffffffff00000000) >> 32
return lbit ^ hbit
}
2019-04-18 01:39:44 +00:00
func New(hcode HashCode, comp compare.Compare) *HashMap {
2019-04-16 19:22:07 +00:00
hm := &HashMap{}
hm.growfactor = 2
2019-04-18 01:39:44 +00:00
hm.GetHash = hcode
hm.Compare = comp
2019-04-21 05:31:39 +00:00
initcap := uint(8)
2019-04-21 20:46:07 +00:00
hm.table = make([]*avlTree, initcap, initcap)
hm.countNextGrow()
2019-04-16 19:22:07 +00:00
return hm
}
2019-04-21 20:46:07 +00:00
// func (hm *HashMap) grow() {
// if hm.size >= hm.growsize {
// newsize := hm.size << 1
// newtable := make([]*Bucket, newsize, newsize)
// hm.growsize = newsize - newsize>>2
// for _, bucket := range hm.table {
// if bucket != nil {
// cur := bucket.head
// hash := hm.GetHash(cur.Key)
// index := hash % newsize
// // var bkt *Bucket
// bkt := newtable[index]
// if bkt == nil {
// bkt = &Bucket{size: 1}
// newtable[index] = bkt
// bkt.head = &bNode{Value: cur.Value, Key: cur.Key}
// cur = cur.Next
// }
// for ; cur != nil; cur = cur.Next {
// bn := &bNode{Value: cur.Value, Key: cur.Key}
// bkt.size++
// bn.Next = bkt.head
// bkt.head = bn
// }
// }
// hm.table = newtable
// }
// }
// }
func (hm *HashMap) countNextGrow() {
hm.growsize = uint(len(hm.table)) << 2
}
2019-04-21 05:31:39 +00:00
func (hm *HashMap) grow() {
if hm.size >= hm.growsize {
newsize := hm.size << 1
2019-04-21 20:46:07 +00:00
newtable := make([]*avlTree, newsize, newsize)
for _, cur := range hm.table {
if cur != nil {
cur.Traversal(func(k, v interface{}) bool {
hash := hm.GetHash(k)
index := hash % newsize
bkt := newtable[index]
if bkt == nil {
bkt = avlNew(hm.Compare)
newtable[index] = bkt
}
bkt.Put(k, v)
return true
})
2019-04-21 05:31:39 +00:00
}
}
2019-04-21 20:46:07 +00:00
hm.table = newtable
hm.countNextGrow()
2019-04-21 05:31:39 +00:00
}
}
2019-04-16 19:22:07 +00:00
func (hm *HashMap) Put(key, value interface{}) {
hash := hm.GetHash(key)
2019-04-21 05:31:39 +00:00
tlen := uint(len(hm.table))
index := hash % tlen
2019-04-21 20:46:07 +00:00
bkt := hm.table[index]
2019-04-21 05:31:39 +00:00
2019-04-21 20:46:07 +00:00
if bkt == nil {
bkt = avlNew(hm.Compare)
hm.table[index] = bkt
}
if bkt.Put(key, value) {
hm.size++
hm.grow()
}
2019-04-21 05:31:39 +00:00
2019-04-21 20:46:07 +00:00
// if bkt == nil {
// nbucket := &Bucket{size: 1}
// hm.table[index] = nbucket
// nbucket.head = &bNode{Value: value, Key: key}
2019-04-21 05:31:39 +00:00
// hm.size++
2019-04-21 20:46:07 +00:00
// hm.grow()
// return
// }
// cur := bkt.head
2019-04-21 05:31:39 +00:00
2019-04-21 20:46:07 +00:00
// for cur.Next != nil {
// if hm.Compare(key, cur.Key) == 0 {
// cur.Key = key
// cur.Value = value
// return
2019-04-18 01:39:44 +00:00
// }
2019-04-21 20:46:07 +00:00
// cur = cur.Next
2019-04-18 01:39:44 +00:00
// }
2019-04-21 20:46:07 +00:00
// bn := &bNode{Value: value, Key: key}
// hm.size++
// bkt.size++
2019-04-18 01:39:44 +00:00
2019-04-21 20:46:07 +00:00
// bn.Next = bkt.head
// bkt.head = bn
2019-04-18 01:39:44 +00:00
2019-04-21 20:46:07 +00:00
// hm.grow()
}
2019-04-21 05:31:39 +00:00
2019-04-21 20:46:07 +00:00
func (hm *HashMap) Get(key interface{}) (interface{}, bool) {
hash := hm.GetHash(key)
2019-04-21 05:31:39 +00:00
2019-04-21 20:46:07 +00:00
tlen := uint(len(hm.table))
index := hash % tlen
bkt := hm.table[index]
if bkt != nil {
return bkt.Get(key)
}
2019-04-21 05:31:39 +00:00
2019-04-21 20:46:07 +00:00
return nil, false
2019-04-16 19:22:07 +00:00
}