开发者学堂课程【Go 语言核心编程 - 数据结构和算法: 数据结构和算法-哈希表(散列)2】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/627/detail/9866
数据结构和算法-哈希表(散列)2
一、基于 hashtable 的雇员关系系统的思路分析
1、首先新建一个文件夹 hashtable ,然后建一个文件叫 main.go ,最后建立一个包package,根据分析写出一个主函数:
先写一个主函数,然后写一个 id 和名字。
package main
Import (
“
fmt
”
)
//定义 Emp
type Emp struct {
Id int
Name string
Next * Emp
}
//方法待定..
//定义 EmpLink
//我们这里的 EmpLink 不带表头(也可以带表头),即第一个节点就存放雇员
type EmpLink struct {
Head * Emp
}
//方法待定..
//1.添加员工的方法,保证添加时,编号是从小到大,要保障进去就要有辅助指针
func (this *EmpLink) Insert(emp *Emp) {
cur := thie.Head
// 这是辅助指针
var pre *Emp = nil
//这是一个辅助指针 pre 在 cur 前面
// 如果当前的 EmpLink 就是一个空链表,用 cur 和 pre 判断都一样。
if cur == nil {
this.Head = emp
return
}
}
// 如果不是一个空链表,给 emp 找到对应的位置并插入(难点),代码不是一下子就写完的。
//思路是让 cur 和 emp 比较,然后让 pre 保持在 cur 前面,这样子一旦找到,就可以把他们加进去了。这个 id 就是库员里的 id。如果 cur.Id > emp.Id 成立,就说明找到位置了,反之就继续走,直到找到为止。还有可能一直都找不到,找不到就退出。
for {
If cur !=n
//比较
if cur.Id > emp.Id {
//找到位置
break
}
Pre = cur
//保证同步
cur = cur.Next
}else {
Break
}
}
//退出时,我们看下是否将 emp 添加到链表最后
if cur == nil {
pre.Next = emp
emp.Next = cur
} else {
pre.Next = emp
emp.Next = cur
}
}
验证:
Pre 等于空,cur 不等于空,三不大于四,往下走。
继续 pre 不等于 cur
让 pre 指向 cur,考虑中间前头,中间没有毛病
考虑中间节点特别大,那么这个逻辑接着走,前面代码一样 for 循环,原先链表结构3指向6,6指向9,6不大于12 ,继续把pre往前挪,然后让cur 往前挪,cur 不等于 nil ,就在比较 cur 和 id 依旧不大于,pre又往下走,cur 又要走,但是后面为空,这个时候,判断完了,继续判断cur 是否等于nil 。因此上下两个逻辑是一样的,就可以删改为
pre.Next = emp
emp.Next = cur
如果上来就是空链表,什么都没有,本身就没有指向,这个时候看看是否能加入,首先将 cur 指向 head ,head 是空的, 也没有指向,他是一个没有带头结点的指向表,让 head 直接指向 id 然后就可以走了,第一个节点进来就可以直接往下走了。
代码漏洞:再加一个比头节点还小的数,会把头一个踢掉,直接指向 head 就结束了。
假设有三个链表,第一个 id 假设等于3,第二个等于6,第三个等于9,验证代码。
由上述验证可以将以上代码删减成
pre.Next = emp
emp.Next = cur
//定义 hashtable ,含有一个链表数组,他是一个数组但是里面含有的是链表,所以叫他链表数组。可以用空间换时间。
type HashTable struct {
LinkArr [7] EmpLink
}
//给 HashTable 编写 Insert 雇员的方法.(需要动一动脑筋),需要把雇员提前指出来,添加时要确定雇员添加到哪一个链表。
func (this *HashTable) Insert (emp *Emp) {
//使用散列函数,确定将该雇员添加到哪个链表根据程序员水平不一样,什么也都会不一样,可以根据不同需求改变。
LinkNo := this.HashFun(emp.Id)
//使用对应的链表添加
this.LinkArr[linkNo].Insert(emp *Emp) //
}
//编写一个散列方法,给一个 id 就可以返回到要找到地方。有可能出现二级链表
func (this *HashTable) HashFun(id int) int {
return id%7
//得到一个值,就是对于的链表的下标
}
func main () {