STL unordered_set(hahs_set)详解

STL   unordered_set(hahs_set)底层
#include
#include
#include
#include
#include
#include
using namespace std;
//被人代码 在VS2015下编写
//介绍hashset 与hashmap之前先了解 底层的hashtable
//C++11 用unordered_set 与unordered_map 代替hash_set 与hash_map
/*
hash函数:映射函数 将某个值映射到 某一个位置
负载系数:元素个数/hash表(使用开链法 时将大于1)
碰撞:不同元素被映射到相同位置 
解决碰撞方法:线性探测 二次探测 开链...
惰性删除:只标记该元素被删除 而非真正删除该元素

SGI STL 中bucket采用vector 每个bucket中的元素为一个链表

hashtable迭代器 必须维持与整个bucket的关系
//我摘取了 STL中 operator++的源代码
const node* old=cur;
cur=cur->next;
if(!cur)
{
size_type bucket=ht->bkt(old->val);
while(!cur&&++bucketbucket.size())
cur=ht->buckets[bucket];
return *this;
}
hashtable 只定义了前向操作 所以无后退操作 也无你想迭代器
//数组形式的hashtable 的表格大小需要为素数 (因为使用合数会使某些二进制位失效
增大碰撞几率)
开链法 不严格要求表的大小为质数 但是SGI的STL严格使用质数
是从53-4294967291ul 的无符号 质数 逐渐成两倍增长的趋势
用户指定大小后 内部返回大于该大小的最小质数为 表格大小
补充:C++11用 unordered_set 代替 hash_set 
其动态扩张大小次序改为 16 32 64 ...
hashtable 的插入有两种insert_unique 与insert_equal
hashtable 判断是否重建的方法:
当元素个数(含新插入元素)大于表的bucket个数时 便找下一个质数
,重新遍历整个表计算hash函数 插入到新位置
hashtable 的clear与copy_from都是一个一个删除与拷贝的 
*/
//下面介绍 hash_set的常用函数
//程序在VS2015 下编写 编译器提醒我 hash_set will be removed ,
//于是使用C++11中的unordered_set 代替
/*
构造函数 
unordered_set(size_t n,const hasher& hf,const key_equal& eq);
unordered_set(InputIterator f,Inputterator l,size_t n, Inputsize_t n,const hasher& hf,const key_equal& eq);
成员函数
pair Str2;
	}
};
int main(void)
{
	string array[7] = {"zhang","li","sun","zhao","wang","wu","zheng"};
	int len = sizeof(array) / sizeof(array[0]);//这样也可以 只是没试过
	unordered_set MySet(array,array+len/*,100*/);//此处可以指定大小
	//unordered_set MySet(array, array + len);
	typedef unordered_set::iterator S_Ite;
	pair bInsert;
	bInsert = MySet.insert("zhang");//底层调用 hashtable的insert_unique
	if (bInsert.second)
	{
		cout <<"insert success!"<< *(bInsert.first) << endl;
	}
	string array2[] = {"1","2","3"};
	MySet.insert(array2,array2+3);
	cout << "bucket count: " << MySet.bucket_count() << endl;
	//64 这是c++11的改变  他把增长序列变为二次幂了(有一点奇怪 为什么 不是16呢)
	size_t Lastcount = MySet.bucket_count();
	/*
	int i = 0;
	while (1)
	{
		MySet.reserve(i);
		if (Lastcount != MySet.bucket_count())
		{
			Lastcount = MySet.bucket_count();
			cout << Lastcount << endl;
		}
		++i;
	}
	*/
	//打印结果为 16 32 64 128 与vector扩张是一样的 和SGI的不一样
	S_Ite ite = MySet.begin();
	while (ite != MySet.end())
	{
		cout << *ite << ":" << MySet.count(*ite) << endl;
		//输出每个元素的个数 对于unordered 来说 只会是 1或者0
		++ite;
	}
	puts("");
	for (int i = 0; i < (int)MySet.bucket_count(); ++i)
	{
		if (0 != MySet.bucket_size(i))
		{
			//输出每个桶里的元素个数
			cout << MySet.bucket_size(i);
		}
	}
	ite=MySet.find("zhang");
	if (MySet.end() != ite)
	{
		cout << "\nI find :" << *ite << endl;
	}
	return 0;
}


你可能感兴趣的:(STL)