unordered_map 随机元素

对于hash的结构来说

思路1:直接随机内部list 即可,但是数据量大的话 iter 要定位起来是个很麻烦的事情

df9ed18a47db044c6106fb2864320b7daf4.jpg

思路2:先随机到一个可用bucket 然后再里面随机一个元素即可

这样存在一个问题,就是bucket会随着rehash  resize等扩容而变化,但是size会变化很大 甚至远小于,这样的话随机的时候就很难随机到该元素,rehash 让多余太多的bucket 去掉,但是rehash的代价本身就比较大, 因此这个方法不够好,单纯的解决这个问题 可以考虑用map来随机化,但是查找性能又会下降。因此这种情况就要考虑自己实现一个适合这种情况的hash_map 来处理这个问题 而不是用std::unordered_map了

const std::string & GatewayLoginInfo::RandomMember()
{
	if (this->uuid_to_session_id.size() <= 0)
	{
		return  empty_string;
	}
	//way2 to random
	int max_random_counter = this->uuid_to_session_id.bucket_count();
	int iter = max_random_counter * 2;
	int bucket;
	while ((--iter) >= 0)
	{
		//	find a not empty bucket
		bucket = rand() % max_random_counter;
		int size = this->uuid_to_session_id.bucket_size(bucket);
		if (size > 0)
		{
			// this bucket is not empty
			//大部分情况下  size 一般为0 1 因此比way1 好很多
			auto this_bucket_iter = this->uuid_to_session_id.begin(bucket);
			int counter = rand() % size;
			while (--counter >= 0)
			{
				++this_bucket_iter;
			}
			return this_bucket_iter->first;
		}
	}
	return empty_string;
	//way1 to random
	/*auto it = this->uuid_to_session_id.begin();
	int counter = rand() % this->uuid_to_session_id.size();
	while (counter--)
	{
	++it;
	}
	return it->first;*/
}

泛型版本:


//从hash表中随机一个元素
template< typename HashMap>
auto unordered_map_random_member_if(HashMap & hash, const std::function<bool(const decltype(hash.begin())&)> &cb)->decltype(hash.begin())
{
	if (hash.size() <= 0)
	{
		return  hash.end();
	}
	int max_random_counter = hash.bucket_count();
	int iter = max_random_counter * 2;
	int bucket;
	while ((--iter) >= 0)
	{
		//	find a not empty bucket
		bucket = rand() % max_random_counter;
		int size = hash.bucket_size(bucket);
		if (size > 0)
		{
			// this bucket is not empty
			//大部分情况下  size 一般为0 1
			auto this_bucket_iter = hash.begin(bucket);
			int counter = rand() % size;
			while (--counter >= 0)
			{
				++this_bucket_iter;
			}
			if (cb(this_bucket_iter))
			{
				return (this_bucket_iter);
			}
		}
	}
	return hash.end();
}

//从hash表中随机一个元素
template< typename HashMap>
auto unordered_map_random_member(HashMap & hash)->decltype(hash.begin())
{
	has_find_one = false;
	if (hash.size() <= 0)
	{
		return  hash.end();
	}
	int max_random_counter = hash.bucket_count();
	int iter = max_random_counter * 2;
	int bucket;
	while ((--iter) >= 0)
	{
		//	find a not empty bucket
		bucket = rand() % max_random_counter;
		int size = hash.bucket_size(bucket);
		if (size > 0)
		{
			// this bucket is not empty
			//大部分情况下  size 一般为0 1
			auto this_bucket_iter = hash.begin(bucket);
			int counter = rand() % size;
			while (--counter >= 0)
			{
				++this_bucket_iter;
			}
			return (this_bucket_iter);
		}
	}
	return hash.end();
}

 

非hash结构的std::map的 随机元素 TODO

 

 

转载于:https://my.oschina.net/kkkkkkkkkkkkk/blog/1858117

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值