STL—unordered_set和unordered_map使用及源码剖析

文章目录

  • 容器hashtable
    • 概述
    • 源码剖析
    • hashtable使用
  • 容器unordered_set、unordered_multiset、unordered_map和unordered_multimap
    • 概述

容器hashtable

概述

hashtable就是散列表(哈希表)
哈希表采用散列技术,散列技术是一种查找技术,而且是一种"一步到位"的查找技术

散列技术存储元素的时候是按照函数f对应的规律来存储元素,使得我们存储元素的位置为f(key)

顺序/二分/差值查找:要查找元素key->与待查找集合中的元素对比->找到要查找元素的位置index
散列查找:要查找元素key->直接通过函数f计算出要查找元素的位置index

STL—unordered_set和unordered_map使用及源码剖析_第1张图片
hashtable最开始只有53个桶,当元素个数大于桶的个数时,桶的数目扩大为最接近当前桶数两倍的质数,实际上,桶数目的增长顺序被写死在代码里:

static const unsigned long __stl_prime_list[__stl_num_primes] = {
        53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
        49157, 98317, 196613, 393241, 786433, 1572869, 3145739,
        6291469, 12582917, 25165843, 50331653, 100663319,
        201326611, 402653189, 805306457, 1610612741,
        3221225473ul, 4294967291ul};

源码剖析

template<class Value, 	//节点的实值类别
		 class Key, 	//节点的键值类别
		 class HashFcn,	//hash function的函数类别
         class ExtractKey, //从节点中取出键值的方法(仿函数)
		 class EqualKey,	//判断键值是否相同(仿函数)
         class Alloc=alloc>	//空间配置器
class hashtable {
public:
    typedef HashFcn 	hasher;
    typedef EqualKey 	key_equal;
    typedef size_t 		size_type;
private:
    hasher hash;
    key_equal equals;
    ExtractKey get_key;
    
    typedef __hashtable_node<Value> node;
    vector<node*, Alloc> buckets;	// 保存桶的vector
    size_type num_elements;
public:
    size_type bucket_count() const { return buckets.size(); }
};

// 节点
template<class Value>
struct __hashtable_node {
    __hashtable_node *next;
    Value val;
};

// 迭代器
template<class Value, class Key, class HashFen, class ExtractKey, class EqualKey, class Alloc>
struct __hashtable_iterator {
    node *cur;
    hashtable *ht;
};

hashtable使用

hashtable<pair<const string, int>, 
		  string, 
		  hash<string>, 
		  select1st<pair<const string, int>>, 
		  equal_to<string>, 
		  alloc> siht(100, hash<string>(), equal_to<string>());

cout << siht.size() << endl; 							// 0
cout << siht.bucket_count() << endl;					// 193
siht.insert_unique(make_pair(string("jjhou"), 95));
siht.insert_unique(make_pair(string("sabrina"), 90));
siht.insert_unique(make_pair(string("mjchen"), 85));
cout << siht.size() << endl;							// 3
cout << siht.bucket_count() << endl;					// 193
cout << siht.find(string("sabrina"))->second << endl; 	//90
cout << siht.find(string("jjhou"))->second << endl;		//95
cout << siht.find(string("mjchen"))->second << endl;	//85
#include 
#include 
using namespace std;
int main()
{
	//hash_table
	//
	//note: hash_table has no default ctor
	hashtable<int, int, hash<int>, identity<int>, equal_to<int>, alloc>
		iht(50, hash<int>, euqal_to<int>);	//指定50个buckets
	cout << iht.size() << endl;		//0
	cout << iht.bucket_count() << endl;	//53
	cout << iht.max_bucket_count() << endl;	// 4294967291
	
	iht.insert_unique(59);
	iht.insert_unique(63);
	iht.insert_unique(108);
	iht.insert_unique(2);
	iht.insert_unique(53);
	iht.insert_unique(55);
	
	cout << iht.size() << endl;	//6

	//声明一个hashtable迭代器,将所有节点值打印出来
	hashtable<int, int, hash<int>, identity<int>, equal_to<int>, alloc>
		::iterator ite = iht.begin();
	for(int i = 0; i < iht.size(); ++i, ++ite)
		cout << *ite << ' '; // 53 55 2 108 59 63
	cout << endl;
	
	//遍历所有buckets,如果其节点个数不为0,就打印出节点个数
	for(int i = 0; i < iht.bucket_count(); ++i)
	{
		int n = iht.elems_in_bucket(i);
		if(n != 0)
			cout << "bucket[ " << i << " ] has " << n << " elems." << endl;
	}
	//bucket[0] has 1 elems.
	//bucket[2] has 3 elems.
	//bucket[6] has 1 elems.
	//bucket[10] has 1 elems.
}

容器unordered_set、unordered_multiset、unordered_map和unordered_multimap

概述

C++11引入的容器unordered_setunordered_multisetunordered_mapunordered_multimap更名自gcc2.9的容器hash_sethash_multisethash_maphash_multimap,其底层封装了hashtable.用法与setmultisetmapmultimap类似
STL—unordered_set和unordered_map使用及源码剖析_第2张图片

你可能感兴趣的:(STL,c++,stl)