哈希表,是根据关键字值(Key)直接进行访问的数据结构,它通过把关键字映射到表中一个位置(数组下标)来直接访问,以加快查找关键值的速度。这个映射函数叫做哈希函数,存放记录的数组叫做哈希表
给定表M,存在函数f(key),存在函数f(key),对任意的关键字值key,待入函数后若能得到包含该关键字的表中地址,称表M为哈希表,函数f(key)为哈希函数。
//哈希表用来访问
#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;
}
//哈希表用来排序
//时间复杂度O(表长+n),n为元素个数
//哈希表排序长度,需要超过最大待排序的数字
#include <stdio.h>
int main() {
int random[10] = { 999, 1, 444, 7, 20, 9, 1, 3, 7, 7 };
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;
}
利用哈希函数,将关键字(key)转化为整数再对表长取余,从而关键字值转化为哈希表的表长范围内的整数
拉链法解决冲突,构造哈希表
将所有哈希函数结果相同的结点连接在同一个单链表中。
若选定的哈希表长度为m,则可将哈希表定义为一个长度为m的指针数组t[0-m-1],指针数组中的每个指针指向哈希函数结果相同的单链表。
插入value:
将元素value插入哈希表,若元素value的哈希函数值为hash_key,将value对应的节点以头插法的方式插入到以t[hash_key]为头指针的单链表中。
查找value:
若元素value的哈希函数值为hash_key,遍历以t[hash_key]为头指针的单链表,查找链表各个节点的值域是否为value.
#include <stdio.h>
#include <vector>
//哈希表即为普通的单链表构成
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(NULL){}
};
//整数哈希函数,直接取余
int hash_func(int key, int table_len) {
return key % table_len;
}
//将元素插入哈希表
void insert(ListNode* hash_table[], ListNode* node, int table_len) {
int hash_key = hash_func(node->val, table_len);
node->next = hash_table[hash_key]; //使用头插法插入节点
hash_table[hash_key] = node;
}
bool search(ListNode* hash_table[], int value, int table_len) {
int hash_key = hash_func(value, table_len);
ListNode* head = hash_table[hash_key];
while (head)
{
if (head->val == value) {
return true;
}
head = head->next;
}
return false;
}
//TABLE_LEN取为质数,冲突会比其他数字少
int main() {
const int TABLE_LEN = 11;
ListNode* hash_table[TABLE_LEN] = { 0 };
std::vector<ListNode*> hash_node_vec;
int test[8] = { 1,1,4,9,20,30,150,500 };
for (int i = 0; i < 8; i++) {
hash_node_vec.push_back(new ListNode(test[i]));
}
for (int i = 0; i < hash_node_vec.size(); i++) {
insert(hash_table, hash_node_vec[i], TABLE_LEN);
}
printf_s("Hash table:\n");
for (int i = 0; i < TABLE_LEN; i++) {
printf_s("[%d]:", i);
ListNode* head = hash_table[i];
while (head) {
printf_s("->%d", head->val);
head = head->next;
}
printf_s("\n");
}
printf_s("\n");
printf_s("Test search:\n");
for (int i = 0; i < 10; i++) {
if (search(hash_table, i, TABLE_LEN) ){
printf_s("%d is in the hash table.\n", i);
}
else {
printf_s("%d is not in the hash table.\n", i);
}
}
return 0;
}
结果如下:
哈希map与STLmap
#include <stdio.h>
#include <map>
#include <string>
struct ListNode {
std::string key;
int val;
ListNode* next;
ListNode(int x):val(x),next(NULL){}
};
int main() {
std::map<std::string, int> hash_map;
std::string str1 = "abc";
std::string str2 = "aaa";
std::string str3 = "xxxxxx";
hash_map[str1] = 1;
hash_map[str2] = 2;
hash_map[str3] = 100;
if (hash_map.find(str1) != hash_map.end()) {
printf_s("%s is in hash_map, value is %d\n", str1.c_str(), hash_map[str1]);
}
std::map<std::string, int>::iterator it;
for (it = hash_map.begin(); it != hash_map.end(); it++) {
printf{ "hash_map[%s] = %d\n", it->first.c_str(), it->second };
}
return 0;
}