一 unordered_map
底层实现完全由hash表代替,所以没有自动排序,适合用于只查找元素的情况,对底层hash表来说,每个节点都有一个键值(key)和实值(value)
小例子
#include<unordered_map>
#include<unordered_set>
int main()
{
unordered_map<int, int> unmap;
for (int i = 0; i < 30; i++)
{
unmap.insert(make_pair(i, i));//inset 的返回值//pair<unordered_map<int, string>::iterator, bool> ret; 第二个参数代表是否插入成功
}
cout << "umap[3]:" << unmap[3] << endl;//他支持[]运算符
unordered_map<int, int>::iterator it = unmap.find(3);//查找,不存在返回end()
for (int i = 0; i < unmap.bucket_count(); i++)
{
cout << "bucket" << i << ":";
for (auto it = unmap.begin(i); it != unmap.end(i); it++)
{
cout << " " << (*it).first << "second:" << (*it).second;
}
cout << endl;
}
return 0;
}
结果
map和unordered_map的比较:
内部实现机理
map:map内部实现了一个红黑树,该结构具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素,因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行这样的操作,故红黑树的效率决定了map的效率。unordered_map: unordered_map内部实现了一个哈希表,因此其元素的排列顺序是杂乱的,无序的
部分stl源码
unordered_map类
class hash_map
{
private:
typedef hashtable<pair<const Key, T>, Key, HashFcn, //<pair<const Key, T>传入,说明hash表上链表节点挂载<pair<const Key, T>
select1st<pair<const Key, T> >, EqualKey, Alloc> ht; //申明hash表
ht rep; //创建hash表
public:
typedef typename ht::key_type key_type;
typedef T data_type;
typedef T mapped_type;
typedef typename ht::value_type value_type;
typedef typename ht::hasher hasher;
typedef typename ht::key_equal key_equal;
typedef typename ht::size_type size_type;
typedef typename ht::difference_type difference_type;
typedef typename ht::pointer pointer;
typedef typename ht::const_pointer const_pointer;
typedef typename ht::reference reference;
typedef typename ht::const_reference const_reference;
typedef typename ht::iterator iterator;
//注意此处和unordered_set不同,定义的iterator迭代器不是ht::const_iterator,说明可以更改值,键值不可改(key)实际就是修改实值(value)
typedef typename ht::const_iterator const_iterator;
hasher hash_funct() const { return rep.hash_funct(); }
key_equal key_eq() const { return rep.key_eq(); }
operator[]重载
T& operator[](const key_type& key)
{
return rep.find_or_insert(value_type(key, T())).second;
//先find函数找到key值对应的节点,返回second也就是实值value
//如果没有找到,那么会新建一个节点,键值为key,返回second也就是实值value
//返回引用,所以可以修改节点的value值
}
find()
iterator find(const key_type& key)
{
size_type n = bkt_num_key(key); //找到在buckets中落脚点
node* first;
for ( first = buckets[n];
first && !equals(get_key(first->val), key); //键值相等或first指向null时返回
first = first->next)
{}
return iterator(first, this); //返回一个迭代器
}
insert()
pair<iterator, bool> insert(const value_type& obj) //返回中second代表是否插入成功
{ return rep.insert_unique(obj); } //抵用hash表插入函数,不能重复插入相同键值key的元素
二 unordered_set
和unordered_map一样, 底层实现完全由hash表代替,没有自动排序,对底层hash表来说,键值就是实值,适合用于只查找元素的情况
小例子
#include<unordered_set>
int main()
{
unordered_set<int> unset;
unordered_set<int>::iterator it;
for (int i = 0; i < 10;i++)
{
unset.insert(i);
}
unordered_set<int>::iterator itf= unset.find(3);//查找,不存在返回end()
for (unsigned i = 0; i < unset.bucket_count(); ++i)
{
cout << "bucket" << i << ":";
for (auto it = unset.begin(i); it != unset.end(i); ++it)
{
cout << " " << *it;
}
cout << std::endl;
}
return 0;
}
结果
set和unordered_ser的比较:
参考map的。
部分stl源码
unordered_set类
class hash_set
{
private:
typedef hashtable<Value, Value, HashFcn, identity<Value>,
EqualKey, Alloc> ht; //申明hash表
ht rep; //创建hash表
public:
typedef typename ht::key_type key_type;
typedef typename ht::value_type value_type;
typedef typename ht::hasher hasher;
typedef typename ht::key_equal key_equal;
typedef typename ht::size_type size_type;
typedef typename ht::difference_type difference_type;
typedef typename ht::const_pointer pointer;
typedef typename ht::const_pointer const_pointer;
typedef typename ht::const_reference reference;
typedef typename ht::const_reference const_reference;
typedef typename ht::const_iterator iterator; //注意此处,默认const_iterator
typedef typename ht::const_iterator const_iterator;
hasher hash_funct() const { return rep.hash_funct(); }
key_equal key_eq() const { return rep.key_eq(); }
find()
iterator find(const key_type& key)
{
size_type n = bkt_num_key(key); //找到在buckets中落脚点
node* first;
for ( first = buckets[n];
first && !equals(get_key(first->val), key); //键值相等或first指向null时返回
first = first->next)
{}
return iterator(first, this); //返回一个迭代器
}
insert()
pair<iterator, bool> insert(const value_type& obj)
{
pair<typename ht::iterator, bool> p = rep.insert_unique(obj); //在hash表的插入中会判断有没有重复元素
return pair<iterator, bool>(p.first, p.second); //first是迭代器,second代表是否成功插入
}
三 总结
无序(unordered)map,set,底层就是哈希表,就是查找速度非常的快,但是建立哈希表就比较费时,在常数内,map,set底层是红黑树,有序性是最大的优点,但是空间占用率高,因为每一个节点都需要额外保存父节点,孩子节点以及红/黑性质,使得每一个节点都占用大量的空间。所以灵活运用。
同时,map与set对应有multimap和multiset,所以unordered_map和unordered_set也有对应的,具体用到在了解吧