数据结构与算法之哈希表
文章目录
哈希表
哈希表是一种将value值与key值构建映射关系,以达到快速查询的数据结构。
在c++STL中实现了三种哈希结构:数组、set、map。
其中数组就没什么好介绍的了。本文主要介绍set、map这两种哈希结构。此外,也实现了一个简单的哈希表。
一、set集合介绍
1、std::set集合
(1)底层实现:红黑树
(2)是否排序:根据key值进行排序
(3)key值能否重复:key值不能重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(logn)
(6)增删效率:O(logn)
2、std::multiset集合
(1)底层实现:红黑树
(2)是否排序:根据key值进行排序
(3)key值能否重复:key值可重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(logn)
(6)增删效率:O(logn)
3、std::unordered_set集合
(1)底层实现:哈希表
(2)是否排序:无序
(3)key值能否重复:key值不可重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(1)
(6)增删效率:O(1)
二、map集合介绍
1、std::map
(1)底层实现:红黑树
(2)是否排序:根据key值进行排序
(3)key值能否重复:key值不能重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(logn)
(6)增删效率:O(logn)
2、std::multimap集合
(1)底层实现:红黑树
(2)是否排序:根据key值进行排序
(3)key值能否重复:key值可重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(logn)
(6)增删效率:O(logn)
3、std::unordered_map集合
(1)底层实现:哈希表
(2)是否排序:无序
(3)key值能否重复:key值不可重复
(4)key值能否修改:key值不能修改
(5)查询效率:O(1)
(6)增删效率:O(1)
哈希表的简单实现
MyHashSet类
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class MyHashSet{
public:
MyHashSet(const int& range);
~MyHashSet();
void add(int key); //添加键值
void remove(int key); //删除键值
bool contains(int key);//查找键值
private:
int KeyRange;
vector<ListNode*> HashTable;
};
构造函数
为了尽量避免哈希冲突建议将rang设置为素数且尽量设置的比较大
MyHashSet::MyHashSet(const int& range){
KeyRange = range;
for(int i = 0; i < range; ++i){
HashTable.push_back(nullptr);
}
}
析构函数
MyHashSet::~MyHashSet(){
for(int i = 0; i < KeyRange; ++i){
if(HashTable[i] == nullptr)
continue;
ListNode* cur = HashTable[i];
HashTable[i] = nullptr;
while(cur != nullptr){
ListNode* temp = cur->next;
delete cur;
cur = temp;
}
}
}
添加键值
void MyHashSet::add(int key){
if(this->contains(key))//判断该key是否已经存在
return;
int n = key % KeyRange;
ListNode* newNode = new ListNode(key);
newNode->next = HashTable[n];
HashTable[n] = newNode;
}
移除键值
void MyHashSet::remove(int key){
int n = key % KeyRange;
ListNode* dummy = new ListNode(0); //虚头结点
dummy->next = HashTable[n];
ListNode* cur = dummy->next;
ListNode* pre = dummy;
while(cur != nullptr){
if(cur->val = key){
pre->next = cur->next;
delete cur;
break;
}
pre = cur;
cur = cur->next;
}
HashTable[n] = dummy->next;
delete dummy;
}
查找键值
bool MyHashSet::contains(int key){
int n = key % KeyRange;
ListNode* cur = HashTable[n];
while(cur != nullptr){
if(cur->val == key)
return true;
cur = cur->next;
}
return false;
}
以上代码如有问题,请及时留言。
总结
MyHashSet类只是对哈希表的简单实现,当数据量很大时不会自动扩展数组,及重新排列key值。需要用到相关哈希函数时,建议使用STL标准库中的set、map。当然如果数据量不大,也可以用数组实现哈希,例如统计字符串中小写字符的数量。