【go密碼學】-Hash

Hash(散列函數)

簡單說就是一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數。
一個優秀的Hash算法,將能實現:node

  • 正向快速:給定明文,快速計算出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
}
相關文章
相關標籤/搜索