C++ unordered_map与unordered_set

一 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也有对应的,具体用到在了解吧

猜你喜欢

转载自blog.csdn.net/GreedySnaker/article/details/114002446