一、简介
1.1 哈希表/函数
哈希表通过哈希函数对输入的key进行处理,将key存放在相应的索引上的链表;
1.2 特性
- 哈希表内存扩张:当哈希表中,索引的链表过长时,会自动扩张一倍;扩张时需要时间为O(logN),且当元素转移时需要时间O(N),故总的时间复杂度为O(NlogN);
- 均分性:哈希表内部链表的长度会维持相对的稳定;
- 查找性能:当通过key进行查找,即可通过哈希函数获取相应的索引,在通过遍历其中的链表;时间复杂度几乎为常数级别;
- 哈希碰撞:哈希表通过在每个索引上挂上链表来解决;
1.3 哈希实践
- 设计一种结构,满足以下功能:
- 1)插入函数,将key加入,且重复;
- 2)将原本结构的key删除
- 3)通过随机函数获取一个key
/*----------------------------------------------------------------------
> File Name: Demo.cpp
> Author: Jxiepc
> Mail: Jxiepc
> Created Time: Wed 02 Mar 2022 10:41:07 AM CST
----------------------------------------------------------------------*/
/**
* 设计一种结构,满足以下功能:
* 1)插入函数,将key加入,且重复;
* 2)将原本结构的key删除
* 3)通过随机函数获取一个key
* */
#include <map>
#include <iostream>
#include <stdlib.h>
#include <time.h>
template<class T = std::string>
class Hash {
public:
void insert(T key, int val) {
auto f = t_map.find(key);
if(f == t_map.end()) {
t_map[key] = val;
idx_map[val] = key;
m_size++;
}
}
void del(T key) {
auto tmp = idx_map[m_size-1]; // 取出最后一个元素
int tmp_idx = t_map[key];
// 修改索引
t_map[tmp] = tmp_idx;
idx_map[tmp_idx] = tmp;
m_size--;
}
T getRandom() {
srand((unsigned)time(NULL));
int v = rand() % (m_size - 1);
std::cout << "rand val: " << v << " key: ";
return idx_map[v];
}
void pprint() {
for(int i=0; i<m_size; ++i) {
std::cout << "key: " << i
<< " val: " << idx_map[i] << std::endl;
}
}
private:
std::map<T, int> t_map;
std::map<int, T> idx_map;
int m_size = 0;
};
int main(int argc, char* argv[])
{
Hash<std::string> p;
p.insert("x", 0);
p.insert("a", 1);
p.insert("b", 2);
p.insert("c", 3);
p.insert("d", 4);
p.pprint();
std::cout << "获取随机值" << std::endl;
std::cout << p.getRandom() << std::endl;
std::cout << "删除后:" << std::endl;
p.del("a");
p.pprint();
return 0;
}