概念(一)hash table _ 哈希表(中)

1. 哈希思想

哈希表 hash table 也称散列表, 是由数组演化而来, 底层依赖 数组 支持按照下标快速 访问元素的特性;

1.1 hash 原理

哈希表利用的是 数组按照下标访问元素时, 其时间复杂度为 O(1) 这样的特性;

实际操作时: 通过哈希函数, 将元素的键值映射为下标, 然后, 将对应的数据存储在 数组中 对应的下标的位置;

当按照键值 查询元素时, 使用同样的哈希函数, 将键值转化为 数组下标, 从数组中 这个下标对应的位置取数据。

作用, 可以快速 访问表中的某个 元素, 时间复杂度O(1);

1.2 hash 举例

例如:
以数组举例 :
数组中 索引下标 可当做 成 hash 表中的 key;
数组中 索引所对应的数值 可看成 hash 表中 的 值;

以python 中的 字典举例: dict()

字典中的 关键字 可作为 hash 表中的 key;
字典中 关键字所对应的 内容 作为 hash 表中的 值;

2. 哈希函数

2.1. hash(key)

hash(key): key 表示元素的 键值;
hash(key) 的值 表示经过 哈希函数 计算得到的 哈希值;

2.2 哈希函数的3个基本要求

  1. 哈希函数计算得到的哈希值 是一个 非负整数;
  2. if key1 == key2 , then hash(key1) == hash(key2)
  3. if key1 != key2 , then hash(key1) != hash(key2)

3. 哈希冲突

哈希冲突: 不同的键 经过 同一个哈希函数, 输出的值 映射到同一个 哈希值 上 ;

常用的解决方法: 开放寻址法 和 链表法

3.1. 开放寻址法

一旦出现哈希冲突, 通过重新 探测新位置的方法 解决冲突;

最简单有, 线性探测法:
当向哈希表插入数据时, 如果某个数据经过哈希函数计算后, 对应的存储位置已经被占用了, 则从这个位置开始, 在数组中依次往后查找, 直到找到控线位置为止;

在此基础上,还有 二次探测法, 双重哈希法;

3.2. 链表法

在发生冲突的那些位置, 建立“桶” 或者称 “ 槽”, 即在冲突的位置上 后面接入一个链表;

这样冲突的哈希值, 接着那个位置的 链表中继续存放;

当 N : 表示 哈希表中 元素的个数;
M: 表示 哈希表中 槽的 个数;
则 N / M = K, k 称为装载因子;

装载因子越大, 说明链表长度越长, 哈希表的性能就会越低;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`g_hash_table_new_full` 是 GLib 的一个函数,用于创建一个新的哈希表。它与 `g_hash_table_new` 类似,但是可以指定两个回调函数来释放哈希表的 key 和 value。 函数原型如下: ```c GHashTable* g_hash_table_new_full(GHashFunc hash_func, GEqualFunc key_equal_func, GDestroyNotify key_destroy_func, GDestroyNotify value_destroy_func); ``` 参数说明: - `hash_func`:哈希函数,用于计算 key 的哈希值。 - `key_equal_func`:key 比较函数,用于判断两个 key 是否相等。 - `key_destroy_func`:key 销毁函数,用于释放哈希表的 key。 - `value_destroy_func`:value 销毁函数,用于释放哈希表的 value。 函数返回一个 `GHashTable` 类型的指针,表示创建的哈希表。如果创建失败,则返回 NULL。使用完毕后,需要调用 `g_hash_table_destroy` 函数销毁哈希表。 示例: ```c // 定义 key 和 value 的结构体 typedef struct { char* key; int value; } HashData; // 定义 key 的哈希函数 guint key_hash(gconstpointer key) { return g_str_hash((gchar*)key); } // 定义 key 的比较函数 gboolean key_equal(gconstpointer a, gconstpointer b) { return g_strcmp0((gchar*)a, (gchar*)b) == 0; } // 定义 key 的销毁函数 void key_destroy(gpointer data) { g_free(data); } // 定义 value 的销毁函数 void value_destroy(gpointer data) { g_slice_free(HashData, data); } int main() { GHashTable* hash_table = g_hash_table_new_full(key_hash, key_equal, key_destroy, value_destroy); // 向哈希表插入数据 HashData* data1 = g_slice_new(HashData); data1->key = g_strdup("key1"); data1->value = 1; g_hash_table_insert(hash_table, data1->key, data1); HashData* data2 = g_slice_new(HashData); data2->key = g_strdup("key2"); data2->value = 2; g_hash_table_insert(hash_table, data2->key, data2); // 从哈希表查找数据 HashData* data3 = g_hash_table_lookup(hash_table, "key1"); if (data3 != NULL) { printf("value: %d\n", data3->value); } // 销毁哈希表 g_hash_table_destroy(hash_table); } ``` 在上述示例,我们定义了一个结构体 `HashData`,其包含 key 和 value 两个字段。我们使用 `g_hash_table_new_full` 函数创建了一个哈希表,指定了 key 的哈希函数、比较函数和销毁函数,以及 value 的销毁函数。然后向哈希表插入了两条数据,通过 `g_hash_table_lookup` 函数查找了一条数据,并在最后调用了 `g_hash_table_destroy` 函数销毁了哈希表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值