概述
散列表(Hash table,也叫哈希表),是根据关键码值 (Key value)而直接进行访问的数据结构。
也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
应用实例
使用 Hash table 将该员工的信息(id,name…)存储,当输入该员工的 id 时,要求查找到该员工的所有信息。
package main
import (
"fmt"
"os"
)
// Emp 定义
type Emp struct {
Id int
Name string
Next *Emp
}
// EmpLink 不带表头,即第一个节点就存放员工
type EmpLink struct {
Head *Emp
}
// Insert 添加员工的方法,保证添加时,编号从小到大
func (empLink *EmpLink) Insert(emp *Emp) {
cur := empLink.Head // 辅助指针
var pre *Emp = nil // 辅助指针
// 如果当前的 EmpLink 就是一个空链表
if cur == nil {
empLink.Head = emp
return
}
// 如果当前的 EmpLink 不是一个空链表,让 cur 和 emp 比较,然后让 pre 保持在 cur 前面
for {
if cur != nil {
if cur.Id > emp.Id {
// 找到位置
break
}
pre = cur // 保证同步
cur = cur.Next
} else {
break
}
}
// 退出时,我们看下是否将 emp 添加到链表最后
pre.Next = emp
emp.Next = cur
}
// ShowLink 显示链表信息
func (empLink *EmpLink) ShowLink(no int) {
if empLink.Head == nil {
fmt.Println("链表", no, "为空")
}
cur := empLink.Head // 辅助指针
for {
if cur != nil {
fmt.Println("链表", no, "员工 Id =", cur.Id, "Name =", cur.Name)
cur = cur.Next
} else {
break
}
}
}
// FindById 根据 id 查找对应的员工,如果没有就返回 nil
func (empLink *EmpLink) FindById(id int) *Emp {
cur := empLink.Head
for {
if cur != nil && cur.Id == id {
return cur
} else if cur == nil {
break
}
cur = cur.Next
}
return nil
}
// HashTable 含有一个链表数组
type HashTable struct {
LinkArr [7]EmpLink
}
// Insert 添加员工的方法
func (hashTable *HashTable) Insert(emp *Emp) {
// 使用散列函数,确定将该员工添加到哪个链表
linkNo := hashTable.HashFun(emp.Id)
hashTable.LinkArr[linkNo].Insert(emp)
}
// ShowAll 显示 hashTable 的所有员工
func (hashTable *HashTable) ShowAll() {
for i := 0; i < len(hashTable.LinkArr); i++ {
hashTable.LinkArr[i].ShowLink(i)
}
}
// HashFun 散列方法
func (hashTable *HashTable) HashFun(id int) int {
return id % 7
}
// FindById 根据 id 查找对应的员工,如果没有就返回 nil
func (hashTable *HashTable) FindById(id int) *Emp {
// 使用散列函数,确定将该员工添加到哪个链表
linkNo := hashTable.HashFun(id)
return hashTable.LinkArr[linkNo].FindById(id)
}
func main() {
key := ""
id := 0
name := ""
var hashTable HashTable
for {
fmt.Println("-------------------------")
fmt.Println("添加员工请输入【input】")
fmt.Println("显示员工请输入【show】")
fmt.Println("查找员工请输入【find】")
fmt.Println("退出系统请输入【exit】")
fmt.Println("请输入您的选择")
fmt.Println("-------------------------")
fmt.Scanln(&key)
switch key {
case "input":
fmt.Println("请输入员工Id")
fmt.Scanln(&id)
fmt.Println("请输入员工Name")
fmt.Scanln(&name)
emp := &Emp{
Id: id,
Name: name,
}
hashTable.Insert(emp)
case "show":
hashTable.ShowAll()
case "find":
fmt.Println("请输入员工Id")
fmt.Scanln(&id)
emp := hashTable.FindById(id)
if emp == nil {
fmt.Println("员工不存在,Id=", id)
} else {
fmt.Println("链表", hashTable.HashFun(emp.Id), "找到该员工 Id =", emp.Id, "Name =", emp.Name)
}
case "exit":
os.Exit(0)
default:
fmt.Println("输入错误")
}
}
}