Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hashing/hash_map_collision_with_linkedlist): Add go code #505

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions codes/go/chapter_hashing/hash_map_collision_with_linkedlist.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// File: hash_map_collision_with_linkedlist.go
// Created Time: 2023-05-18
// Author: msk397 (icbigdata@gmail.com)

package chapter_hashing

import (
"fmt"
)

/* 基于数组简易实现的哈希表,hash key冲突时,使用链表存储冲突key */
type arrayHashMapWithLinkedList struct {
buckets []*entryList
}

/* 键值对 int->String */
type entryList struct {
key int
val string
// hash key 冲突时,使用链表连接起来
next *entryList
}

/* 使用别名,简化变量 */
type myMap = arrayHashMapWithLinkedList

var NotFoundKey = "not_found"

/* 初始化哈希表 */
func newArrayHashMapWithLinkedList(bucketSize int) *myMap {
// 初始化数组,包含 100 个桶
buckets := make([]*entryList, bucketSize)
return &arrayHashMapWithLinkedList{buckets: buckets}
}

/* 哈希函数 */
func (a *myMap) hashFunc(key int) int {
size := len(a.buckets)
index := key % size
return index
}

func (a *myMap) getEntry(key int) *entryList {
index := a.hashFunc(key)
pair := a.buckets[index]
if pair == nil {
return nil
}
if pair.key == key {
return pair
}
// 进一步通过链表查询
for pair.next != nil {
pair = pair.next
if pair.key == key {
return pair
}
}
return nil
}

/* 查询操作 */
func (a *myMap) get(key int) string {
entry := a.getEntry(key)
if entry == nil {
return NotFoundKey
}
return entry.val
}

/* 添加操作 */
func (a *myMap) put(key int, val string) {
entry := a.getEntry(key)
if entry == nil {
pair := &entryList{key: key, val: val}
index := a.hashFunc(key)
head := a.buckets[index]
if head != nil {
// hash key 冲突, 头插法,将新节点插入链表的头部
pair.next = head
}
a.buckets[index] = pair
} else {
entry.val = val
}
}

/* 删除操作 */
func (a *myMap) remove(key int) {
index := a.hashFunc(key)
// 置为 nil ,代表删除
pair := a.buckets[index]
if pair == nil {
return
}
if pair.key == key {
next := pair.next
a.buckets[index] = next
} else {
pre := pair
for pair.next != nil {
pair = pair.next
if pair.key == key {
pre.next = pair.next
return
}
pre = pair
}
}
}

/* 获取所有键对 */
func (a *myMap) entrySet() []*entry {
var pairs []*entry
for _, pair := range a.buckets {
for pair != nil {
e := &entry{pair.key, pair.val}
pairs = append(pairs, e)
pair = pair.next
}
}
return pairs
}

/* 获取所有键 */
func (a *myMap) keySet() []int {
var keys []int
for _, pair := range a.buckets {
for pair != nil {
keys = append(keys, pair.key)
pair = pair.next
}
}
return keys
}

/* 获取所有值 */
func (a *myMap) valueSet() []string {
var values []string
for _, pair := range a.buckets {
for pair != nil {
values = append(values, pair.val)
pair = pair.next
}
}
return values
}

/* 打印哈希表 */
func (a *myMap) print() {
for _, pair := range a.buckets {
for pair != nil {
fmt.Println(pair.key, "->", pair.val)
pair = pair.next
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// File: hash_map_collision_with_linkedlist_test.go
// Created Time: 2023-05-18
// Author: msk397 (icbigdata@gmail.com)

package chapter_hashing

import (
"fmt"
"testing"
)

func Test_newArrayHashMapWithLinkedList(t *testing.T) {
/* 初始化哈希表 */
mapp := newArrayHashMapWithLinkedList(100)

/* 添加操作 */
// 在哈希表中添加键值对 (key, value)
mapp.put(12836, "小哈")
mapp.put(15937, "小啰")
mapp.put(16750, "小算")
mapp.put(13276, "小法")
mapp.put(10583, "小鸭")

// 构hash key冲突
mapp.put(20583, "小鸭2")
mapp.put(30583, "小鸭3")
mapp.put(40583, "小鸭4")

fmt.Println("\n添加完成后,哈希表为\nKey -> Value")
mapp.print()

/* 更新key的val */
mapp.put(10583, "小鸭1")
fmt.Println("\n更新学号 10583 ,姓名为 小鸭1")
mapp.print()
/* 查询操作 */
// 向哈希表输入键 key ,得到值 value
name := mapp.get(15937)
fmt.Println("\n输入学号 15937 ,查询到姓名 " + name)

/* 查询操作 */
// 向哈希表输入键 key ,得到值 value
name = mapp.get(20583)
fmt.Println("\n输入学号 20583 ,查询到姓名 " + name)

/* 删除操作 */
// 在哈希表中删除键值对 (key, value)
mapp.remove(12836)
fmt.Println("\n删除 12836 后,哈希表为\nKey -> Value")
mapp.print()

/* 删除操作 */
// 在哈希表中删除键值对 (key, value)
mapp.remove(10583)
fmt.Println("\n删除 10583 后,哈希表为\nKey -> Value")
mapp.print()

/* 删除操作 */
// 在哈希表中删除键值对 (key, value)
mapp.remove(30583)
fmt.Println("\n删除 30583 后,哈希表为\nKey -> Value")
mapp.print()

/* 删除操作 */
// 在哈希表中删除键值对 (key, value)
mapp.remove(40583)
fmt.Println("\n删除 40583 后,哈希表为\nKey -> Value")
mapp.print()

/* 遍历哈希表 */
fmt.Println("\n遍历键值对 Key->Value")
for _, kv := range mapp.entrySet() {
fmt.Println(kv.key, " -> ", kv.val)
}

fmt.Println("\n单独遍历键 Key")
for _, key := range mapp.keySet() {
fmt.Println(key)
}

fmt.Println("\n单独遍历值 Value")
for _, val := range mapp.valueSet() {
fmt.Println(val)
}
}