Go数据结构与算法之散列表

概述

散列表(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("输入错误")
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值