已有两个散列函数,构造n个散列函数
h0 = g() + 0 * h()
h1 = g() + 1 * h()
h2 = g() + 2 * h()
package main
import (
"encoding/json"
"fmt"
)
type entity struct {
k interface{}
v interface{}
}
type HashMap struct {
Bucket []entity
Cap int
Len int
}
func NewHashMap(cap int) *HashMap {
if cap <= 1 {
cap = 10
}
return &HashMap{make([]entity, cap), cap, 0}
}
func (h *HashMap) Set(key interface{}, value any) (ok bool) {
bs, _ := json.Marshal(key)
h0 := hash(string(bs))
h1 := hash1(string(bs))
index := h0 % uint64(h.Cap)
if h.Bucket[index].k != nil {
for j := 0; j < h.Cap; j++ {
index = (h0 + uint64(j)*h1) % uint64(h.Cap) //new hash
if h.Bucket[index].k == nil || h.Bucket[index].k == key {
if h.Bucket[index].k == nil {
h.Len++
}
h.Bucket[index].k = key
h.Bucket[index].v = value
return true
}
}
return false
} else {
h.Bucket[index].k = key
h.Bucket[index].v = value
h.Len++
return true
}
}
func (h *HashMap) SetWithGrow(key interface{}, value any) {
bs, _ := json.Marshal(key)
h0 := hash(string(bs))
h1 := hash1(string(bs))
index := h0 % uint64(h.Cap)
if h.Bucket[index].k != nil {
for j := 0; j < h.Cap; j++ {
index = (h0 + uint64(j)*h1) % uint64(h.Cap) //new hash
if h.Bucket[index].k == nil || h.Bucket[index].k == key {
if h.Bucket[index].k == nil {
h.Len++
}
h.Bucket[index].k = key
h.Bucket[index].v = value
return
}
}
// 越界了,扩容
entities := h.RangeCopy()
entities = append(entities, entity{key, value}) //所有实体
h.Cap *= 2
h.Len = 0
h.Bucket = make([]entity, h.Cap, h.Cap)
for j := 0; j < len(entities); j++ {
h.SetWithGrow(entities[j].k, entities[j].v)
}
} else {
h.Bucket[index].k = key
h.Bucket[index].v = value
h.Len++
return
}
}
func (h *HashMap) Get(key interface{}) (value interface{}, exist bool) {
bs, _ := json.Marshal(key)
h0 := hash(string(bs))
h1 := hash1(string(bs))
index := h0 % uint64(h.Cap)
for j := 0; j < h.Cap; j++ {
index = (h0 + uint64(j)*h1) % uint64(h.Cap)
if h.Bucket[index].k == key {
return h.Bucket[index].v, true
}
}
return nil, false
}
func (h *HashMap) Delete(key interface{}) {
bs, _ := json.Marshal(key)
h0 := hash(string(bs))
h1 := hash1(string(bs))
index := h0 % uint64(h.Cap)
for j := 0; j < h.Cap; j++ {
index = (h0 + uint64(j)*h1) % uint64(h.Cap)
if h.Bucket[index].k == key {
h.Bucket[index].k = nil
h.Bucket[index].v = nil
h.Len--
return
}
}
}
func (h *HashMap) RangeCopy() (res []entity) {
res = make([]entity, 0, h.Len)
for i := 0; i < h.Cap; i++ {
if h.Bucket[i].k != nil {
res = append(res, entity{h.Bucket[i].k, h.Bucket[i].v})
}
}
return res
}
func main() {
//
//fmt.Println(hash("999"))
//fmt.Println(hash1("999"))
//return
mp := NewHashMap(1)
mp.Set("你好", "你好呀")
//fmt.Println(mp.Set("hello", "hhhh"))
mp.SetWithGrow("hello", "world")
mp.SetWithGrow("hello1", "world1")
mp.SetWithGrow("hello2", "world2")
mp.SetWithGrow("hello3", "world3")
mp.SetWithGrow("hello4", "world4")
mp.SetWithGrow("hello5", "world5")
mp.SetWithGrow("hello6", "world6")
mp.Delete("hello6")
fmt.Println(mp.Get("hello6"))
fmt.Println(mp.Get("hello5"))
//mp.SetWithGrow("hello5", "-----")
fmt.Println(mp.Get("hello5"))
fmt.Println(mp.Get("hello3"))
fmt.Println(mp.RangeCopy())
fmt.Println(mp.Len)
fmt.Println(mp.Cap)
}
func pow(x, n int) int {
if n == 0 {
return 1
} else {
for (n & 1) == 0 {
n, x = n>>1, x*x
}
}
result := x
n >>= 1
for n != 0 {
x *= x
if n&1 == 1 {
result *= x
}
n >>= 1
}
return result
}
func hash(str string) (res uint64) {
factor := ")k+,p-m~90$#2(*&6q}ev73541]n{fl['?|c"
str = str + factor[:16-(len(str)%16)]
for start, end := 0, len(str)/16; end > 0; start, end = start+16, end-1 {
h0 := uint64(0)
for i := 15; i >= 0; i-- {
h0 += uint64(str[start+i]-byte(i))*uint64(pow(36, i)) ^ uint64(factor[(i+start)%36])
}
h0 *= 0x12345
res += (res >> 30) ^ h0<<34
res += (res >> 32) | (h0 << 32) ^ uint64(start*start*start) ^ uint64(factor[start%36])
res += (res>>16)&(h0<<48) ^ uint64(factor[35-start%36]) ^ uint64(start-end*end)
res += (res >> 17) | (h0 << 47) ^ uint64(start*start)
}
res += 235791113<<32 | 1719232931>>32
return res
}
func hash1(str string) (res uint64) {
factor := ")k+,p-m~90$#2(*&6q}ev73541]n{fl['?|c"
str = str + factor[:16-(len(str)%16)]
for start, end := 0, len(str)/16; end > 0; start, end = start+16, end-1 {
h0 := uint64(0)
for i := 15; i >= 0; i-- {
h0 += uint64(str[start+i]-byte(i))*uint64(pow(36, i)) ^ uint64(factor[(i+start)%36])
}
h0 *= 0x54321
res += (res >> 32) | (h0 << 32) ^ uint64(start*start*start) ^ uint64(factor[start%36])
res += (res>>16)&(h0<<48) ^ uint64(factor[35-start%36]) ^ uint64(start-end*end)
res += (res >> 17) | (h0 << 47) ^ uint64(start*start)
res += (res >> 30) ^ h0<<34
}
res += 1719232931<<32 | 235791113>>32
return res
}