博主很久没有更新过STL源码剖析这个系列的文章了,主要是因为大部分STL常用的容器,博主都已经发过文章了,今天博主带着大家把哈希表也模拟实现一下。
前言
那么这里博主先安利一下一些干货满满的专栏啦!
手撕数据结构https://blog.csdn.net/yu_cblog/category_11490888.html?spm=1001.2014.3001.5482
这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏https://blog.csdn.net/yu_cblog/category_11464817.html
这里是STL源码剖析专栏,这个专栏将会持续更新STL各种容器的模拟实现。
STL源码剖析https://blog.csdn.net/yu_cblog/category_11983210.html?spm=1001.2014.3001.5482
什么是开散列哈希桶
开散列哈希桶是一种哈希表的实现方式,它的原理是通过哈希函数将键(key)映射到一个存储桶(bucket)的索引位置,每个桶中可以存储多个键值对。
以下是开散列哈希桶的基本原理:
- 初始化:创建一个固定大小的桶数组,每个桶都可以存储一个或多个键值对。
- 哈希函数:选择一个合适的哈希函数,它可以将键映射到桶的索引位置。哈希函数应该是快速计算的,并且应该尽可能地将键均匀地分布在桶数组中。
- 插入操作:当要插入一个键值对时,首先使用哈希函数计算出键的哈希值。根据哈希值找到对应的桶,然后将键值对存储在该桶中。如果多个键映射到同一个桶,可以使用链表、数组等数据结构来解决冲突,将它们存储在同一个桶中。
- 查找操作:当要查找一个键时,使用哈希函数计算出键的哈希值。根据哈希值找到对应的桶,并在该桶中搜索键值对。如果有多个键映射到同一个桶,可以遍历桶中的键值对,找到匹配的键。
- 删除操作:删除操作类似于查找操作。首先使用哈希函数计算出键的哈希值,找到对应的桶,并在桶中搜索键值对。如果找到匹配的键值对,将其从桶中删除。
- 开散列哈希桶的优点是可以处理哈希冲突,即多个键映射到同一个桶的情况。通过合理选择哈希函数和解决冲突的方法,可以使桶中的键值对均匀分布,提高查找、插入和删除的效率。然而,如果哈希函数选择不当或者数据集分布不均匀,可能导致冲突增加,从而降低了性能。因此,在设计和使用开散列哈希桶时,选择适当的哈希函数和解决冲突的策略非常重要。
代码Github地址
C++https://github.com/Yufccode/BitCode/tree/main/Cpp
open_hash.h
#pragma once
//tips: deepcopy hasn't realize
#include
UnorderedMap.h
#pragma once
#include"open_hash.h"
using namespace std;
//tips: deepcopy hasn't realize
namespace yfc
{
template>
class unordered_map
{
struct MapKeyOfT
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
public:
typedef typename HashTable, Hash, MapKeyOfT>::iterator iterator;//µü´úÆ÷
//¼ÇµÃ¼Ótypename
iterator begin()
{
return _ht.begin();
}
iterator end()
{
return _ht.end();
}
public:
pair insert(const pair& kv)
{
return _ht.insert(kv);
}
bool erase(const K& key)
{
return _ht.erase(key);
}
V& operator[](const K& key)
{
pair ret = _ht.insert(make_pair(key, V()));
return ret.first->second;
}
private:
HashTable, Hash, MapKeyOfT>_ht;
};
//=================²âÊÔ==================
void test_map1()
{
unordered_mapdict;
dict.insert(make_pair("a", "A"));
dict.insert(make_pair("b", "B"));
dict.insert(make_pair("c", "C"));
dict.insert(make_pair("d", "D"));
unordered_map::iterator it = dict.begin();
while (it != dict.end())
{
cout << it->first << ":" << it->second << endl;
++it;
}
}
void test_map2()
{
string arr[] = { "Æ»¹û","Æ»¹û","Ï㽶","Î÷¹Ï","Æ»¹û","Ï㽶","Î÷¹Ï","Æ»¹û","Î÷¹Ï","Ï㽶","Î÷¹Ï","Î÷¹Ï" };
//HashTablecountHT;
unordered_mapmap;
for (auto& str : arr)
{
map[str]++;
}
for (auto& kv : map)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
}
UnorderedSet.h
#pragma once
#include"open_hash.h"
using namespace std;
//tips: deepcopy hasn't realize
namespace yfc
{
template>
class unordered_set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename HashTable::iterator iterator;//迭代器
//记得加typename
iterator begin()
{
return _ht.begin();
}
iterator end()
{
return _ht.end();
}
public:
pair insert(const K& key)
{
return _ht.insert(key);
}
bool erase(const K& key)
{
return _ht.erase(key);
}
private:
HashTable_ht;
};
//=================测试==================
void test_set1()
{
unordered_sets;
s.insert(2);
s.insert(3);
s.insert(1);
s.insert(2);
s.insert(5);
s.insert(-1);
unordered_set::iterator it = s.begin();
while (it != s.end())
{
cout << *it << endl;
++it;
}
}
}