search——哈希表,哈希碰撞,开放寻址,线性探查

index = hash + i

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 <= 0 {
		cap = 100
	}
	return &HashMap{make([]entity, cap), cap, 0}
}

func (h *HashMap) Set(key interface{}, value any) (ok bool) {
	bs, _ := json.Marshal(key)
	index := hash(string(bs)) % uint64(h.Cap)
	if h.Bucket[index].k != nil {
		for index < uint64(h.Cap) {
			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
			}
			index++
		}
		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)
	index := hash(string(bs)) % uint64(h.Cap)
	if h.Bucket[index].k != nil {
		for index < uint64(h.Cap) {
			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
			}
			index++
		}
		// 越界了,扩容
		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)
	index := hash(string(bs)) % uint64(h.Cap)
	for index < uint64(h.Cap) {
		if h.Bucket[index].k == key {
			return h.Bucket[index].v, true
		}
		index++
	}
	return nil, false
}

func (h *HashMap) Delete(key interface{}) {
	bs, _ := json.Marshal(key)
	index := hash(string(bs)) % uint64(h.Cap)
	for index < uint64(h.Cap) {
		if h.Bucket[index].k == key {
			h.Bucket[index].k = nil
			h.Bucket[index].v = nil
			h.Len--
			return
		}
		index++
	}
}

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() {
	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
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

metabit

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值