简单说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
一个优秀的Hash算法,将能实现:node
正向快速
:给定明文,快速计算出hash值。逆向困难
:给定hash值,很难逆推出明文。输入敏感
:原始输入信息修改一点消息,产生的hash值看起来应该都有很大不一样。冲突避免
:很难找到2段不一样的明文,使他们的hash值相同。//将任何长度的字符串,经过运算,散列成0-15整数 func HashCode(key string) int { var index int = 0 index = int(key[0]) for k := 0; k < len(key); k++ { //1103515245是个好数字,使经过hashCode散列出的0-15的数字的几率是相等的 index *= (1103515245 + int(key[k])) } index >>= 27 index &= 16 - 1 return index }
将v存到hash表中的步骤:算法
package main import ( "./HMap" "fmt" ) func main() { //每一个空间都存有一个链表头 HMap.InitBuckets() HMap.AddKeyValue("a","hello world") HMap.AddKeyValue("abc","hello China") fmt.Println(HMap.GetValueByKey("a")) fmt.Println(HMap.GetValueByKey("abc")) }
package HMap import "../LNodes" //实现hashmap原理 //建立长度为16的数组 var buckets = make([]*LNodes.Node,16) func InitBuckets() { for i:=0;i<16;i++{ buckets[i]= LNodes.CreateHead(LNodes.KValue{"head","node"}) } } //将任何长度的字符串,经过运算,散列成0-15整数 //经过hashCode散列出的0-15的数字的几率是相等的 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 } //先hashmap中保存键值对 func AddKeyValue(key string ,value string ) { //计算key散列的结果,数组下标 var nIndex = HashCode(key) //在数组中得到头结点 var headNode = buckets[nIndex] //得到当前链表的尾节点 var tailNode = LNodes.TailNode(headNode) //添加节点 LNodes.AddNode(LNodes.KValue{key,value},tailNode) } //获取键值对 func GetValueByKey(key string ) string { var nIndex = HashCode(key) var headNode = buckets[nIndex] //经过链表查询对应key 的value var value = LNodes.FindValueByKey(key,headNode) return value }
package LNodes import "fmt" type KValue struct { Key string Value string } type Node struct { Data KValue NextNode *Node } //建立头结点 func CreateHead(data KValue ) *Node { var head = &Node{data,nil } return head } //添加节点 func AddNode(data KValue ,node *Node) *Node { var newNode = &Node{data ,nil} node.NextNode = newNode return newNode } //节点的遍历 func ShowNodes(head *Node) { node:= head for { if node.NextNode !=nil { fmt.Println(node.Data) node = node.NextNode }else { break } } fmt.Println(node.Data) } //得到当前链表的尾节点 func TailNode(head *Node) *Node { node :=head for { if node.NextNode == nil { return node } else { node = node.NextNode } } } func FindValueByKey(key string ,head *Node) string { node :=head for { if node.NextNode!=nil { if node.Data.Key == key { return node.Data.Value } node = node.NextNode }else { break } } return node.Data.Value }