前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文搞懂Go实现HashTable

一文搞懂Go实现HashTable

原创
作者头像
海风极客
发布2024-03-06 22:30:35
910
发布2024-03-06 22:30:35

HashTable,即哈希表,也叫散列表。它是一种利用哈希函数(Hash Function)进行数据存储的数据结构,通过把键(Key)映射到哈希表中的一个位置来访问记录,以加快查找的速度。哈希函数的作用是将键映射到哈希表中的位置,而哈希表存储数组则用于存储记录。

HashTable的特点主要有以下几点:

  1. 快速查找:通过哈希函数,可以直接定位到存储的数据位置,因此查找速度快。
  2. 支持高效的插入和删除操作:由于哈希表是通过哈希函数来确定数据存储位置,因此插入和删除数据时只需要计算一次哈希函数即可,所以哈希表的插入和删除操作速度快。
  3. 冲突问题:哈希函数并不是完美的,有时会出现多个键映射到同一个位置的情况,这种情况称为哈希冲突。为了解决哈希冲突问题,哈希表通常采用拉链法或开放寻址法。
  4. 节省空间:哈希表在存储数据时,并不是按照数据的大小来分配空间的,而是根据数据的键来计算其在哈希表中的位置,因此可以更加有效地利用存储空间。

需要注意的是,哈希表也有一些缺点,比如当数据量很大时,哈希表可能会占用较多的内存空间。此外,哈希表的性能也受到哈希函数质量的影响,如果哈希函数设计不好,可能会导致哈希冲突的增加,从而影响哈希表的性能。

下面使用Go语言实现一个HashTable:

代码语言:go
复制
// HashTable 是一个自定义的哈希表结构
type HashTable struct {
	buckets    []*Bucket // 存储桶数组
	loadFactor float64   // 加载因子,当达到某个阈值时触发扩容
	capacity   int       // 当前容量
}

// Bucket 是哈希表中的一个存储桶
type Bucket struct {
	key   interface{}
	value interface{}
	next  *Bucket // 链表下一个节点
}

// NewHashTable 创建一个新的哈希表
func NewHashTable(capacity int, loadFactor float64) *HashTable {
	if capacity <= 0 {
		capacity = 1
	}
	if loadFactor <= 0 || loadFactor >= 1 {
		loadFactor = 0.75
	}
	return &HashTable{
		buckets:    make([]*Bucket, capacity),
		loadFactor: loadFactor,
		capacity:   capacity,
	}
}

// hash 计算键的哈希值并返回其在存储桶数组中的索引
func (h *HashTable) hash(key interface{}) int {
	hasher := fnv.New32a()
	_, _ = hasher.Write([]byte(fmt.Sprintf("%v", key)))
	return int(hasher.Sum32()) % h.capacity
}

// Put 向哈希表中添加或更新一个键值对
func (h *HashTable) Put(key, value interface{}) {
	index := h.hash(key)
	bucket := h.buckets[index]

	// 查找是否存在相同的键
	for bucket != nil {
		if bucket.key == key {
			bucket.value = value // 更新值
			return
		}
		bucket = bucket.next
	}

	// 创建新节点并添加到链表末尾
	newNode := &Bucket{key: key, value: value}
	if h.buckets[index] == nil {
		h.buckets[index] = newNode
	} else {
		lastBucket := h.buckets[index]
		for lastBucket.next != nil {
			lastBucket = lastBucket.next
		}
		lastBucket.next = newNode
	}

	// 检查是否需要扩容
	if float64(len(h.buckets))*h.loadFactor < float64(len(h.buckets)+len(h.buckets[:index])+1) {
		h.resize()
	}
}

// Get 从哈希表中获取一个键对应的值
func (h *HashTable) Get(key interface{}) (interface{}, bool) {
	index := h.hash(key)
	bucket := h.buckets[index]

	for bucket != nil {
		if bucket.key == key {
			return bucket.value, true
		}
		bucket = bucket.next
	}

	return nil, false
}

// Delete 从哈希表中删除一个键值对
func (h *HashTable) Delete(key interface{}) {
	index := h.hash(key)
	bucket := h.buckets[index]
	prev := &bucket

	for bucket != nil {
		if bucket.key == key {
			// 移除节点
			*prev = bucket.next
			return
		}
		prev = &bucket.next
		bucket = bucket.next
	}
}

// resize 重新调整哈希表的大小
func (h *HashTable) resize() {
	newCapacity := h.capacity * 2
	newBuckets := make([]*Bucket, newCapacity)

	for _, bucket := range h.buckets {
		for bucket != nil {
			index := h.hash(bucket.key) // 重新计算新索引
			next := bucket.next
			bucket.next = newBuckets[index]
			newBuckets[index] = bucket
			bucket = next
		}
	}

	h.buckets = newBuckets
	h.capacity = newCapacity
}

使用方式:

代码语言:go
复制
func main() {  
	hashTable := NewHashTable(10, 0.75)  
  
	hashTable.Put("name", "John")  
	hashTable.Put("age", 30)  
	hashTable.Put("city", "New York")  
  
	fmt.Println("Initial HashTable:", hashTable)  
	fmt.Println("Length:", hashTable.Len())  
	fmt.Println("Is Empty?", hashTable.IsEmpty())  
	fmt.Println("Contains 'name'?", hashTable.Contains("name"))  
  
	hashTable.Iterate()  
  
	value, found := hashTable.Get("age")  
	if found {  
		fmt.Println("Found age:", value)  
	}  
  
	hashTable.Delete("age")  
	fmt.Println("HashTable after deleting 'age':", hashTable)  
  
	// Trigger resize  
	for i := 0; i < 100; i++ {  
		hashTable.Put(fmt.Sprintf("key%d", i), i)  
	}  
  
	fmt.Println("HashTable after resizing:", hashTable)  
}

总的来说,HashTable是一种非常常见且用途十分广泛的数据结构,使用HashTable可以大大的提高数据的检索速度,是一种非常优秀的结构。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档