【go密码学】-Hash

jincheng828 · · 56 次点击 · · 开始浏览    

Hash(散列函数)

简单说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
一个优秀的Hash算法,将能实现:

  • 正向快速:给定明文,快速计算出hash值。
  • 逆向困难:给定hash值,很难逆推出明文。
  • 输入敏感:原始输入信息修改一点消息,产生的hash值看起来应该都有很大不同。
  • 冲突避免:很难找到2段不同的明文,使他们的hash值相同。

典型的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
}

hash表结构

图片描述

将v存到hash表中的步骤:

  • 通过HashCode计算v的HashCode值,从而确定存在在哪个hash链表下(0-15,共16个hash链).
  • 将v追加的hash链表的尾部.

go实现hash表

main.go

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"))
}

HMap.go

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
}

LNode.go

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
}

本文来自:Segmentfault

感谢作者:jincheng828

查看原文:【go密码学】-Hash

56 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传