一、什么是哈希冲突?
哈希冲突是指哈希函数算出来的地址被别的元素占用了
二、什么是哈希表?
哈希表是基于数组的一种存储方式.它主要由哈希函数和数组构成。
(1)当要存储一个数据的时候,首先用一个函数计算数据的地址,然后再将数据存进指定地址位置的数组里面。这个函数就是哈希函数,而这个数组就是哈希表。
三、如何解决哈希冲突?
(1)开放定址法或散列法:
基本思想是:当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中。其中H(key)为哈希函数,m 为表长,di称为增量序列。增量序列的取值方式不同,相应的再散列方式也不同。
(2)再哈希法:
这种方法是同时构造多个不同的哈希函数:当一个哈希函数地址还产生冲突时,在计算另一个哈希函数地址,直到不再发生冲突为止。
(3)链地址法
这种方法的是将所有哈希地址相同的元素i构成一个单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在单链表中进行。链地址法适用于经常进行插入和删除的情况。
(4)建立公共溢出区
这种方法就是将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。
package main
import (
"fmt"
)
//可以在初始化时自定义
const Size = 10
type Nodes struct {
Val int
Next *Nodes
}
//结构体指针数组
type Table struct {
Array []*Nodes
//value个数
Length int
}
//初始化
func (n *Table) Init() {
n.Array = make([]*Nodes, Size)
n.Length = 0
}
//hash值
func Hash(key int) int {
return key % Size
}
//查找value,没有则返回nil
func (n *Table) Find(value int) *Nodes {
index := Hash(value)
node := n.Array[index]
for node != nil {
if node.Val == value {
return node
} else {
node = node.Next
}
}
return nil
}
/*
AddValue(2)
AddValue(12)
-------------------------------------------
val = 12
next = array[2] {
val = 2
next = array[2] (nil)
}
-------------------------------------------
9
val = 9
next = array[9]
-------------------------------------------
*/
//添加元素
func (n *Table) AddValue(value int) bool {
node := n.Find(value)
//不存在插入,头插法,redis字典也是这样
if node == nil {
index := Hash(value)
newNodes := new(Nodes)
newNodes.Val = value
newNodes.Next = n.Array[index]
n.Array[index] = newNodes
n.Length++
return true
}
node.Val = value
return true
}
//删除元素,找到链表位置,去掉节点
//0 删除成功 -1 失败
func (n *Table) DelNodes(value int) int {
index := Hash(value)
var cur, pre *Nodes
cur = n.Array[index]
//不空,寻找value
for cur != nil {
if cur.Val == value {
//index第一个节点value,则index位置为next
if pre == nil {
n.Array[index] = cur.Next
} else {
//非第一个节点,去点节点就可以
pre.Next = cur.Next
}
//长度减1
n.Length--
return 0
}
//继续寻找value
pre = cur
cur = cur.Next
}
//等于nil则无此值
return -1
}
//输出哈希表值
func (n *Table) Print() {
for i := 0; i < Size; i++ {
cur := n.Array[i]
for cur != nil {
fmt.Printf("%v %v \n ", cur.Val, cur.Next)
cur = cur.Next
}
}
}
func main() {
table := new(Table)
table.Init()
table.AddValue(2)
table.AddValue(12)
table.AddValue(3)
//table.Print()
//fmt.Println()
//table.DelNodes(2)
table.Print()
//fmt.Println(table.Find(99))
}