Go模拟Hash散列表代码实现

什么是哈希表?

哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

记录的存储位置=f(关键字)

这里的对应关系f称为散列函数,又称为哈希(Hash函数),采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表(Hash table)。

哈希表hashtable(key,value) 就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。(或者:把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。) 而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。

数组的特点是:寻址容易,插入和删除困难;

而链表的特点是:寻址困难,插入和删除容易。

那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法,我们可以理解为“链表的数组”,如图:

哈希图.png

左边很明显是个数组,数组的每个成员包括一个指针,指向一个链表的头,当然这个链表可能为空,也可能元素很多。我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。

下面是使用go模拟哈希表代码的简单实现:

package HashMp
​
import (
 "MyHashMap/LinkedNodes"
 "fmt"
)
​
//定义数组的全局变量
var arr [16] *LinkedNodes.Nodes
​
//创建16个顶层节点,放到数组中
func CreateArry (){
 var ar = [16]*LinkedNodes.Nodes{}
​
 for i := 0; i < 16 ; i++ {
 ar[i] = LinkedNodes.CreateArryNode("顶层节点","顶层节点")
 }
 //赋值给全局变量
 arr = ar
 //fmt.Println(ar)
}
​
//向数组中添加键值对
func AddKVToArr(k,v string){
 //先计算出要添加的数据存储到哪个下角标中,这里调用从网上找的算法
 var corner = HashCode(k)
 var head *LinkedNodes.Nodes = arr[corner]
 //调用添加方法
 LinkedNodes.AddChilddNode(k,v,head)
}
​
​
//获取数据
func GetValue(k string) string{
 //先判断是哪个下标存储
 var corner = HashCode(k)
 //获取头节点
 var head *LinkedNodes.Nodes = arr[corner]
 //通过头节点遍历
 for {
 if head.Data.K == k {
 fmt.Println(head.Data.V)
 break
 }else {
 head = head.NextNode
 }
 }
 return ""
}
​
​
//将key转换成数组下标的散列算法,范围16之间
func HashCode(key string) int{
 var index int = 0
 index = int(key[0])
 for  k:= 0; k< len(key) ; k++  {
 index *= (1103515245 + int(key[k]))
 }
 index >>= 27
 index &= 16 - 1
​
 return index
}
package LinkedNodes
​
import "fmt"
​
//申明全局变量,保存头节点
var heads *Nodes  //头节点 为了遍历使用
var currs *Nodes  //当前节点
​
//定义结构存储,存储数组每个下标所包含的单独的map数据
type MP struct {
 K string
 V string
}
//创建结构体,用以申明每个节点
type Nodes struct {
 Data MP  // 数据信息
 NextNode *Nodes  //下一个节点的地址
}
​
//创建头节点
func CreateArryNode(k,v string) *Nodes{
 //创建Node头节点
 var node *Nodes = new(Nodes)
 //封装数据
 node.Data.V = v
 node.Data.K = k
 //指定下一个节点地址,因为还没添加所以是nil
 node.NextNode = nil
​
 //第一次创建头节点
 heads = node
 currs = node
​
 return node
}
​
//向指定的节点中添加数据 第二个参数:指定哪一个节点
func AddChilddNode (k,v string,currs *Nodes) *Nodes{
 var newNode *Nodes = new(Nodes)
 //添加信息
 newNode.Data.K = k
 newNode.Data.V = v
​
 newNode.NextNode = nil
 //挂接节点
 currs.NextNode = newNode
 currs = newNode
 //fmt.Println(curr)
 return newNode
}
​
//遍历指定的节点链表
func ShowNode(n *Nodes){
 var node = n
 for  {
 if node.NextNode != nil{
 fmt.Println(node.Data)
 node = node.NextNode
 }else {
 fmt.Println(node.Data)
 break
 }
 }
}
​
//计算节点个数
func NodesCount ()int{
 var n = heads
 var flag int  //临时存储节点个数变量
 for  {
 if n.NextNode != nil{
 flag+=1
 //fmt.Println(n.data)
 n = n.NextNode
 }else {
 flag+=1
 //fmt.Println(n.data)
 break
 }
 }
 //fmt.Println("节点个数是:",flag)
 return flag
}

测试:

package main
​
import "MyHashMap/HashMp"
​
//程序入口,主执行
func main () {
​
 //创建数组,添加顶层节点
 HashMp.CreateArry()
 //随机向数组的每个下标添加子节点
 HashMp.AddKVToArr("abc","世界")
 HashMp.AddKVToArr("def","和平")
​
 HashMp.GetValue("abc")
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容