例:将学生姓名作为索引。
哈希表:通过索引下标来访问元素。索引下标不一定非得是数字还可是其他。
哈希函数:将姓名等映射为数字下标。外部查询元素,是通过姓名查询,内部是通过姓名对应数字下标,然后通过数字下标来查询。
哈希碰撞:数组有限,学生过多,此时通过哈希函数可能出现,几个学生姓名对应一个数字索引此时产生哈希碰撞。
一般来说哈希表都是用来快速判断一个元素是否出现集合里。
哈希函数是把传入的key映射到符号表的索引上。
哈希碰撞处理有多个key映射到相同索引上时的情景,处理碰撞的普遍方式是拉链法和线性探测法。
一般哈希碰撞有两种解决方法, 拉链法和线性探测法。
拉链法:
小李和小王在索引1的位置发生了冲突,发生冲突的元素都被存储在链表中。 这样我们就可以通过索引找到小李和小王了
线性探测法:
要保证tableSize大于dataSize。 我们需要依靠哈希表中的空位来解决碰撞问题,放了小李,那么就向下找一个空位放置小王的信息
常见的三种哈希结构:
数组
set (集合)
map(映射)
std::unordered_set(不可重复)底层实现为哈希表,std::set (可重复)和std::multiset (不可重复)的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。
当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。
std::map(数值不可重复),std::multimap(数值可重复),std::unordered_map(数值不可重复)
当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法,哈希法也是牺牲了空间换取了时间。