// 哈希结值存放的对象
type HashObj interface{}
// 哈希驻足中链表结点
type IntHashNode struct {
Key int
Value HashObj
Prov *IntHashNode // 上一个结点
Next *IntHashNode // 下一个结点
}
// int 哈希
type IntHash struct {
// TODO 如果读写操作是多线程操作的,那么就需要加锁了
Count int // 当前哈希存放数量
ArrCap int // 创建哈希时数组的容量
NodeArr []*IntHashNode // 存放结点的数组
// TODO 如果需要通过一个首结点遍历所有结点的,需要在链表结点再加一组指针,然后当前结构加一个首位指针
}
// 初始化哈希
func (Self *IntHash) Init(aArrCap int) {
Self.Count = 0
Self.ArrCap = aArrCap
Self.NodeArr = make([]*IntHashNode, aArrCap)
}
// 添加哈希键值
func (Self *IntHash) Add(aKey int, aValue HashObj) {
if aKey < 0 {
aKey *= -1
}
// 加入哈希先弄一份数据
mHashNode := &IntHashNode{
Key: aKey,
Value: aValue,
Prov: nil,
Next: nil,
}
// 取余法得到这个数据存数组的位置
mIndex := aKey % Self.ArrCap
// 如果这个数组的里面还没存数据
if Self.NodeArr[mIndex] == nil {
// 当前插入的数据就可以作为当前位置链表的首个结点
Self.NodeArr[mIndex] = mHashNode
} else {
// 如果这个数组里面已经有了结点数据,进行插入
mTempNode := Self.NodeArr[mIndex]
mTempNode.Prov = mHashNode
mHashNode.Next = mTempNode
Self.NodeArr[mIndex] = mHashNode
}
Self.Count++
}
// 删除哈希
func (Self *IntHash) Del(aKey int) {
if aKey < 0 {
aKey *= -1
}
mIndex := aKey % Self.ArrCap
mHashNode := Self.NodeArr[mIndex]
for mHashNode != nil {
if mHashNode.Key == aKey {
break
}
mHashNode = mHashNode.Next
}
if mHashNode != nil {
if mHashNode.Prov != nil {
// 如果指向上个结点的指针不是nil,需要将指针重新指向
mHashNode.Prov.Next = mHashNode.Next
} else {
// 如果上个指针的指向是nil,就需要将数组当前下标下的数据进行修改
Self.NodeArr[mIndex] = mHashNode.Next
}
if mHashNode.Next != nil {
// 如果哈希的下个指针不是nil的,需要将指针重新指向
mHashNode.Next.Prov = mHashNode.Prov
} else {
// 如果哈希的下个指针是nil,那么无须有其他改动
}
Self.Count--
}
}
// 查找结点
func (Self *IntHash) find(aKey int) *IntHashNode {
if aKey < 0 {
aKey *= -1
}
mIndex := aKey % Self.ArrCap
mHashNode := Self.NodeArr[mIndex]
for mHashNode != nil {
if mHashNode.Key == aKey {
return mHashNode
}
mHashNode = mHashNode.Next
}
return nil
}
// 通过Key获取Value
func (Self *IntHash) GetValue(aKey int) HashObj {
mHashNode := Self.find(aKey)
if mHashNode != nil {
return mHashNode.Value
}
return nil
}
// 打印哈希
func (Self IntHash) printHash() {
fmt.Println("------------- 哈希总内容数量=", Self.Count)
for i, mNode := range Self.NodeArr {
fmt.Println("=====数组下标=", i)
for mNode != nil {
fmt.Println("当前下标中的内容=", mNode.Value, "Key=", mNode.Key)
mNode = mNode.Next
}
}
}
简单的使用:
func TestHash(t *testing.T) {
// 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。
// 也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。
// 这个映射函数叫做散列函数,存放记录的数组叫做散列表。
// 当前方法使用 取余法
// 处理冲突使用 拉链法
mHash := IntHash{}
mHash.Init(10)
for i := 0; i < 20; i++ {
mHash.Add(i, i+20)
}
mHash.printHash()
fmt.Println("=========================================")
mHash.Del(5)
mHash.Del(10)
mHash.printHash()
fmt.Println("=========================================")
fmt.Println(mHash.GetValue(10))
fmt.Println(mHash.GetValue(15))
}
一点点笔记,以便以后翻阅。