1. 什么是哈希表?
哈希表是根据关键码值(Key value)而直接进行访问的数据结构。
哈希表将关键码值映射到表中一个位置来访问记录。
哈希表加快了访问速度。
哈希表有对应的哈希函数,
本质上是一个散列函数,k指代关键字值key。
2. 哈希表的不同之处
哈希表可以根据key的值计算出key的位置,相比于普通列表,查找的时间复杂度由减小为
。
3. 哈希碰撞
(1)什么是哈希碰撞?
对不同的关键字可能得到同一散列地址,即k1≠k2,而f(k1)==f(k2),这种现象称为冲突(英语:Collision),也成为哈希碰撞。
(2)如何处理哈希碰撞?
通过散列法、拉链法可以解决上述问题,参考博客哈希碰撞_顽皮白豌豆的博客-CSDN博客
4. 哈希表的构造:unordered_map
头文件
#include<unordered_map>
(1)初始化
unordered_map<key, value> umap; //模型
unordered_map<string, int> umap; //例子
(2)增加
umap["English"]=90; //使用[]操作符插入值
umap.insert(map<string, int>::value_type("test", 1));
umap.emplace(key, value); //使用变量方式,插入一个元素
umap.emplace("Java", 95); //也可以直接写上key和value的值
(3)删除:根据key删除
auto n = umap.erase("test");
注释:
a. auto是一个C/C++语言存储类型,仅在语句块内部使用,初始化可为任何表达式,其特点是当执行流程进入该语句块的时候初始化可为任何表达式。在C++11标准的语法中,auto被定义为自动推断变量的类型。例中的auto自动将n推断为 unordered_map<int, string>::iterator 型的变量。
b. 如果没有 key="test" ,则返回0。
(4)查找
auto it = umap.find(key);
函数返回一个iterator类型值。
int flag = umap.count(key);
此函数对具有特定键的元素进行计数,如果包含键的元素存在,则返回1,如果容器中不存在具有键的元素,则返回0。
(6)修改
auto it = umap.find(key);
it->second = new_value;
注意:it -> first 不能修改,即key值无法修改。
(7)头尾元素
auto it = umap.begin(); //指向map的第一个元素的地址
auto it = umap.end(); //指向map的最后一个元素之后的地址
(8)访问
umap["Math"]=92;
umap["Physics"]=86;
umap["LinearAlgebra"]=89;
//输出
for(auto x:umap)
{
cout<<x.first<<" "<<x.second<<endl;
}
输出结果如下:
Math 92
Physics 86
LinearAlgebra 89
还可以通过key访问value。
cout<<umap["Math"]; //通过key值来访问value
(9)遍历方法:
直接遍历
for(auto x:umap)
{
cout<<x.first<<" "<<x.second<<endl;
cout<<umap[x.first]<<endl;
}
unordered_map<key, value>::iterator it = umap.begin();
for(it; it != umap.end(); it++)
{
cout<<it->first<<" "<< it->second;
}
用地址遍历
for(auto& a: umap)
{
cout<<a.first<<" "<<a.second;
}
Unordered_map综合例子:
#include<iostream>
#include<unordered_map>
#include<map>
#include <typeinfo>
using namespace std;
int main()
{
//初始化
unordered_map<string, int> umap;
//增加元素
umap["English"] = 90;
umap.insert(map<string, int>::value_type("Test", 100));
umap.emplace("Java", 95);
//第一次遍历打印
for (auto x : umap)
{
cout << x.first << " " << x.second << endl;
}
cout << endl;
//第一次擦除
auto n = umap.erase("Test");
cout << n << endl;
//第二次遍历打印
for (unordered_map<string, int>::iterator it = umap.begin(); it != umap.end(); it++)
{
cout << it->first << " " << it->second << endl;
}
cout << endl;
//第二次擦除,返回值为0(数据类型为unsigned int)
n = umap.erase("Test");
cout << n << " "<< typeid(n).name() <<endl;
//查找,返回值为iterator
auto m = umap.find("Java");
cout << m->first << endl;
//查找,返回值为usgined int
auto p = umap.count("Java");
cout << p << " " << typeid(p).name() << endl;
p = umap.count("Test");
cout << p << endl << endl;
//修改元素
auto it = umap.find("English");
it->second = 72;
for (auto& a : umap)
{
cout << a.first << " " << a.second << endl;
}
return 0;
}
可以验证,打印结果为:
English 90
Java 95
Test 100
1
English 90
Java 95
0 unsigned int
Java
1 unsigned int
0
English 72
Java 95