#pragma once
#include "HashTable.h"
namespace L
{
// 一个类型要做unordered_map/unordered_set的key,要满足支持转换成取模的仿函数和 == 比较
// 一个类型要做set/map的key,要满足支持 < 比较
template >
class unordered_map
{
public:
struct KeyOfT_map
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
typedef typename HashBucket::HashBucket, KeyOfT_map,Hash>::iterator iterator;
typedef typename HashBucket::HashBucket, KeyOfT_map, Hash>::const_iterator const_iterator;
iterator begin()
{
return _bucket.begin();
}
iterator end()
{
return _bucket.end();
}
const_iterator begin() const
{
return _bucket.begin();
}
const_iterator end() const
{
return _bucket.end();
}
V& operator[](const K& key)
{
pair ret = _bucket.Insert(make_pair(key,V()));
return ret.first->second;
}
pair Insert(const pair& kv)
{
return _bucket.Insert(kv);
}
private:
HashBucket::HashBucket, KeyOfT_map,Hash> _bucket;
};
(1)不再以键值对的形式存储数据,而是直接存储数据的值。
(2)容器内部存储的各个元素的值都互不相等,且不能被修改。
(3)不会对内部存储的数据进行排序(这和该容器底层采用哈希表结构存储数据有关。
#pragma once
#include "HashTable.h"
namespace L
{
// 一个类型要做unordered_map/unordered_set的key,要满足支持转换成取模的仿函数和 == 比较
// 一个类型要做set/map的key,要满足支持 < 比较
template >
class unordered_set
{
public:
struct KeyOfT_set
{
const K& operator()(const K& key)
{
return key;
}
};
typedef typename HashBucket::HashBucket::const_iterator iterator;
typedef typename HashBucket::HashBucket::const_iterator const_iterator;
iterator begin()
{
return _bucket.begin();
}
iterator end()
{
return _bucket.end();
}
const_iterator begin() const
{
return _bucket.begin();
}
const_iterator end() const
{
return _bucket.end();
}
pair Insert(const K& key)
{
return _bucket.Insert(key);
}
private:
HashBucket::HashBucket _bucket;
};
C++11新增的unordere系列的map和set与C++98的map和set不同点有:
(1)底层结构不同,C++98底层是红黑树结构,C++11底层是哈希表/哈希桶结构。
(2)查询效率不同,C++11的map和set查询效率更高。
(3)功能略微不同,C++98的map和set支持按key排序,而unordered_map/set不支持排序。
一般当负载因子大于等于0.7,哈希表则开始扩容。
size_t hashi = kv.first % _tables.size();
size_t i = 1;
size_t index = hashi;
while (_tables[index]._state == EXIST)
{
index = hashi + i;
index %= _tables.size();
++i;
}
_tables[index]._kv = kv;
_tables[index]._state = EXIST;
++_n;
return true;
}
二次探测是加i的平方
闭散列最大的缺陷就是空间利用率比较低,这也是哈希的缺陷。
如果key为字符串类型 ,可以提供一个仿函数,把字符串转成size_t类型
size_t operator()(const string& str)
{
size_t hash = 0;
for (auto ch : str)
{
hash += ch;
hash *= 31;
}
return hash;
}
// 一个类型要做unordered_map/unordered_set的key,要满足支持转换成取模的仿函数和 == 比较。
// 一个类型要做set/map的key,要满足支持 < 比较,因为其底层是红黑树,而红黑树本质是二叉搜索树。
//如果哈希桶里的一个桶链接的节点过多,可以把这个桶改为链接红黑树。
同时构造多个不同的哈希函数,等发生哈希冲突时就使用第二个、第三个……等其他的哈希函数计算地址,直到不发生冲突为止。虽然不易发生聚集,但是增加了计算时间。
struct KeyOfT_map
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};