实现一个堆栈散列

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 Tair(兼容Redis),内存型 2GB
简介: 【5月更文挑战第6天】这是一个使用切片实现的散列管理结构,包含散列函数和线性探测再散列策略。结构体`HashStack`有Size、Slots和Data三个字段。代码实现可在提供的GitHub链接中查看。

简介

散列管理结构体。这里实现一个散列,它通过数学方法去寻找空位置放入和取出。

question_ans.png

1 寻找位置

散列管理结构体,使用内置切片作为容器。 当然也可以使用数组,限定大小,这里使用Size去做软性限制。

    type HashStack struct {
        Size  int
        Slots []interface{}
        Data  []interface{}
    }

hashfunction方法采用了简单随机方法来实现散列函数,

而冲突解决则采用 线性探测“加1”再散列函数

key 求余获取散列位置的键

    func (hs *HashStack) HashFuncation(key int) int {
        return key % hs.Size
    }

    func (hs *HashStack) ReHash(old int) int {
        return (old + 1) % hs.Size
    }

2 放入一个键值到堆栈

直接放入,当Slots[hashPosiation]中的 key 不存在时。不冲突,则直接放入

否则
当存在key时,覆盖原有值,Slots[hashPosiation] key 存在 冲突 覆盖。

另一个场景是存在一个不一样的key在当前位置,因此重新散列,以寻找一个新的位置,如果位置总是不为空且不是目标key则继续寻找。

找到的新的位置 不存在冲突则放入,否则覆盖。

     func (hs *HashStack) Put(key int, data interface{}) {
        hashPosiation := hs.HashFuncation(key)
        if hs.Slots[hashPosiation] == nil {
            hs.Slots[hashPosiation] = key
            hs.Data[hashPosiation] = data
        } else {
            if hs.Slots[hashPosiation] == key {
                hs.Data[hashPosiation] = data
            } else {
                nextSlot := hs.ReHash(hashPosiation)

                for hs.Slots[nextSlot] != nil && hs.Slots[nextSlot] != key {
                    nextSlot = hs.ReHash(nextSlot)
                }

                if hs.Slots[nextSlot] == nil {
                    hs.Slots[nextSlot] = key
                    hs.Data[nextSlot] = data
                } else {
                    hs.Data[nextSlot] = data //覆盖
                }
            }
        }
    }

3 从堆栈获取一个值

从散列中获取散列值

首先标记散列值,标记查找起点。

由于 查找key直到遇到空槽,否则stop = true回到起点,最后以字符的方式返回。

func (hs *HashStack) Get(key int) string {

        startSlot := hs.HashFuncation(key)

        var data interface{}
        stop := false
        found := false
        posi := startSlot
        for hs.Slots[posi] != nil && !found && !stop {
            if hs.Slots[posi] == key {
                found = true
                data = hs.Data[posi]
            } else {
                posi = hs.ReHash(posi)
                if posi == startSlot {
                    stop = true
                }
            }

        }
        return ToString(data)

    }

4 查看基本散列信息

func (hs *HashStack) BaseInfo() {
    fmt.Printf("散列插槽数:%v, 散列插槽值:%#v, 散列数据:%#v\n", hs.Size, hs.Slots, hs.Data)
    fmt.Printf("散列ks:%#v\n", hs.Slots)
    fmt.Printf("散列vs:%#v ", hs.Data)
}

5 如何使用散列

初始化一个散列堆栈,并存入值

ht := NewHashStack(100)
ht.Put(1, "c")  
ht.Put(2, "b")
ht.Put(3, "a")
fmt.Printf("散列信息:\n")
ht.BaseInfo()
ht.Put(1, 121)

fmt.Printf("散列信息:\n")
ht.BaseInfo()
fmt.Printf("散列PUT:\n")
ht.Put(35, 121)

获取散列堆栈中的信息

fmt.Printf("散列1位置:%v\n", ht.Get(1))
ht.Put(1, 1331)
fmt.Printf("散列121位置:%v\n", ht.Get(121))
fmt.Printf("散列信息:\n")
ht.BaseInfo()
ht.Put(1, 1332)
fmt.Printf("散列信息2:  \n")
ht.BaseInfo()

6 复杂度评估

最好的场景当然是直接找到位置放入即O(1).
如果是最差的场景,可能遍历了全部散列堆栈也没有找到位置,由于每次数加1都不相同,因此为Size大小。 O(N)

若有兴趣可以看这里:

 https://github.com/hahamx/utools/blob/main/utils/queues/hashStack.go
目录
相关文章
|
9月前
|
设计模式 算法 Java
【数据结构和算法】最大连续1的个数 III
这是力扣的 1004 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。又是一道滑动窗口的典型例题,可以帮助我们巩固滑动窗口算法。这道题很活灵活现,需要加深对题意的变相理解。给定一个二进制数组nums和一个整数k,如果可以翻转最多k个0,则返回数组中连续1的最大个数。
108 2
深入解析哈希表、哈希映射和并发哈希映射的区别,以及死锁的成因和解决方案
深入解析哈希表、哈希映射和并发哈希映射的区别,以及死锁的成因和解决方案
|
4月前
|
算法 安全 Java
介绍一下比较与交换算法
【10月更文挑战第20天】介绍一下比较与交换算法
33 0
|
9月前
|
存储 算法
算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1)(下)
算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1)
42 0
|
9月前
|
算法
算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1)(上)
算法系列--动态规划--⼦数组、⼦串系列(数组中连续的⼀段)(1)
55 0
|
9月前
|
设计模式 算法 Java
【数据结构和算法】交替合并字符串
给你两个字符串word1和word2。请你从word1开始,通过交替添加字母来合并字符串。如果一个字符串比另一个字符串长,就将多出来的字母追加到合并后字符串的末尾。返回合并后的字符串。
128 1
|
存储 算法 C语言
5.堆栈算法
5.堆栈算法
|
机器学习/深度学习 人工智能 C#
C#<数据结构>栈的应用——括号分配问题
C#<数据结构>栈的应用——括号分配问题
87 0
|
算法 数据可视化 C语言
数据结构 | 后缀表达式【深入剖析堆栈原理】
数据结构之堆栈的应用中的后缀表达式讲解,层层递进,由浅入深,带你深刻理解后缀表达式
380 0
数据结构 | 后缀表达式【深入剖析堆栈原理】
|
缓存 算法 Java
如何判断对象是否该被回收(引用计数法、可达性分析算法)
概述 垃圾收集器需要完那些内存需要回收? 什么时候回收? 如何回收?
120 0
如何判断对象是否该被回收(引用计数法、可达性分析算法)