structure/hashmap/hashmap.go
2019-04-21 13:31:39 +08:00

167 lines
2.9 KiB
Go

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