go 拉链法解决哈希冲突

一、什么是哈希冲突?

哈希冲突是指哈希函数算出来的地址被别的元素占用了

二、什么是哈希表?

哈希表是基于数组的一种存储方式.它主要由哈希函数和数组构成。

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

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值