7. 哈希表 1. 哈希表定义和简单应用 哈希表定义: 哈希表,也叫散列表,是根据关键字(key)值 直接进行访问的数据结构,它通过把关键字值映射 到表中的一个位置(数组下标)来直接访问 ,以加快查找关键字值 的速度。这个映射叫做哈希函数 ,存放记录的数组叫作哈希表 .
给定表M,存在, 对任意关键字值key,代入函数若能得到包含该关键字值的表中地址,就称表M为哈希表,函数为哈希函数。
示例1:统计字符串中,各个字符数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <stdio.h> #include <string> int main () { int char_map[128 ] = {0 }; std::string str = "abcdefgaaxxy" ; for (int i = 0 ; i < str.length (); i++){ char_map[str[i]]++; } for (int i = 0 ; i< 128 ; i++){ if (char_map[i] > 0 ){ printf ("%c %d: %d\n" , i, i, char_map[i]); } } return 0 ; } ============================================================= a 97 : 3 b 98 : 1 c 99 : 1 d 100 : 1 e 101 : 1 f 102 : 1 g 103 : 1 x 120 : 2 y 121 : 1
示例2:哈希表排序整数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <stdio.h> int main () { int random[10 ] = {99 , 1 , 444 , 7 , 90 , 1 , 4 , 6 , 888 , 5 }; int hash_map[1000 ] = {0 }; for (int i = 0 ; i < 10 ; i++){ hash_map[random[i]]++; } for (int i = 0 ; i< 1000 ; i++){ for (int j =0 ; j<hash_map[i]; j++){ printf ("%d\n" , i); } } return 0 ; } ====================================================================== 1 1 4 5 6 7 90 99 444 888
2. 任意元素的映射
当遇到负数或非常大的整数 ,如何哈希 ?
当遇到字符串 如何哈希 ?
当遇到无法直接映射的数据类型,如浮点数和数组、对象等如何进行哈希?
利用哈希函数 ,将关键字值key (大整数、字符串、浮点数等)转换为整数在对表长取余 ,从而关键字值被转换为哈希表的表长范围内 的整数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <stdio.h> #include <string> int int_func (int key, int table_len) { return key % table_len; } int string_func (std::string key, int table_len) { int sum = 0 ; for (int i = 0 ; i < key.length (); i++){ sum += key[i]; } return sum % table_len; } int main () { const int TAB_LEN = 10 ; int hash_map[TAB_LEN] = {0 }; hash_map[int_func (9995 , TAB_LEN)]++; hash_map[int_func (5 , TAB_LEN)]++; hash_map[string_func ("abc" , TAB_LEN)]++; hash_map[string_func ("bac" , TAB_LEN)]++; for (int i = 0 ; i< TAB_LEN; i++){ printf ("hash_map[%d] = %d\n" , i, hash_map[i]); } return 0 ; } ============================================================= hash_map[0 ] = 0 hash_map[1 ] = 0 hash_map[2 ] = 0 hash_map[3 ] = 0 hash_map[4 ] = 2 hash_map[5 ] = 2 hash_map[6 ] = 0 hash_map[7 ] = 0 hash_map[8 ] = 0 hash_map[9 ] = 0
哈希冲突 ,解决办法拉链法构造哈希表。
将所有哈希函数结果相同的节点连接在同一个单链表中。若选定哈希表长度为m,则可将哈希表定义为一个长度为m的指针数组t[0..m-1],指针数组中每个指针指向哈希函数结果相同的单链表。
插入value
:
将元素value
插入哈希表,若元素value
的哈希函数值为hash_key
,将value
对应的节点以头插法
方式插入到t[hash_key]
为头指针的单链表
中。
查找value
:
若元素value
的哈希函数值 为hash_key
, 遍历以t[hash_key]
为头指针的单链表 ,查找链表的各个节点的值域是否为value
。