C++之unordered_set和unordered_map

一、unordered系列关联式容器

在C++98中,STL提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到log_2

N,即最差情况下需要比较红黑树的高度次,当树中的节点非常多时,查询效率也不理想。最好

的查询是,进行很少的比较次数就能够将元素找到,因此在C++11中,STL又提供了4个

unordered系列的关联式容器,这四个容器与红黑树结构的关联式容器使用方式基本类似,只是

其底层结构不同

1.1 unordered_map

1.2 unordered_map的文档介绍

  1. unordered_map是存储<key, value>键值对的关联式容器,其允许通过keys快速的索引到与

其对应的value。

  1. 在unordered_map中,键值通常用于惟一地标识元素,而映射值是一个对象,其内容与此

键关联。键和映射值的类型可能不同。

  1. 在内部, unordered_map没有对<kye, value>按照任何特定的顺序排序, 为了能在常数范围内

找到key所对应的value,unordered_map将相同哈希值的键值对放在相同的桶中。

  1. unordered_map容器通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭

代方面效率较低。

  1. unordered_maps实现了直接访问操作符(operator[]),它允许使用key作为参数直接访问value。

  2. 它的迭代器至少是前向迭代器。

1.3unordered_map的使用

unordered_map成员函数

unordered_map的使用

cpp 复制代码
void test_unordered_map1()
{
	unordered_map<string, string> dict;
	dict.insert(make_pair("insert", "插入"));
	dict.insert(make_pair("love", "爱"));
	dict["sort"] = "排序";
	dict["miss"];
	dict["miss"] = "想念、错过";

	unordered_map<string, string>::iterator it = dict.begin();
	while (it != dict.end())
	{
		cout << it->first << ":" << it->second << endl;
		++it;
	}
	cout << endl;
}
int main()
{
    test_unordered_map1();
    return 0;
}

注意:

1、[ ]实际调用哈希桶的插入操作,用参数key与V()构造一个默认值往底层哈希桶

中插入,如果key不在哈希桶中,插入成功,返回V(),插入失败,说明key已经在哈希桶中,

将key对应的value返回。

2、unordered_map中key是不能重复的,因此count函数的返回值最大为1

1.4unordered_set的介绍

1、unordered_set是一种容器,它以任意顺序存储唯一的元素,并允许根据元素的值快速检索单个元素。

2、在unordered_set中,元素的值同时也是其键,用于唯一标识该元素。键是不可变的,因此,unordered_set中的元素一旦存入容器就不能被修改------不过可以插入和移除。

3、在内部,unordered_set中的元素并不按任何特定顺序排序,而是根据它们的哈希值被组织到各个桶中,以便通过元素的值直接快速访问单个元素(平均具有常数级的时间复杂度)。

4、unordered_set在通过键访问单个元素方面比有序集合容器更快,不过在对其部分元素进行范围迭代时,通常效率较低。

5、unordered_set的迭代器至少是前向迭代器。

1.5unordered_set的使用

unordered_set成员函数

unordered_set的使用

cpp 复制代码
void test_unordered_set1()
{
	unordered_set<int> us;
	us.insert(2);
	us.insert(3);
	us.insert(2);
	us.insert(1);
	us.insert(0);

	unordered_set<int>::iterator it = us.begin();
	while (it != us.end())
	{
		cout << *it << endl;
		++it;
	}
	cout << endl;
}
int main()
{
    test_unordered_set1();
    return 0;
}

注意:unordered_set只能去重,不能左到排序

1.6map、set、unordered_map、unordered_set性能测试

cpp 复制代码
void test_performance()
{
	const size_t N = 1000000;

	unordered_set<int> us;
	set<int> s;

	vector<int> v;
	v.reserve(N);
	srand((size_t)time(0));
	for (size_t i = 0; i < N; ++i)
	{
		v.push_back(rand() + 1);
	}

	size_t begin1 = clock();
	for (auto e : v)
	{
		s.insert(e);
	}
	size_t end1 = clock();
	cout << "set insert:" << end1 - begin1 << endl;

	size_t begin2 = clock();
	for (auto e : v)
	{
		us.insert(e);
	}
	size_t end2 = clock();
	cout << "unordered_set insert:" << end2 - begin2 << endl;


	size_t begin3 = clock();
	for (auto e : v)
	{
		s.find(e);
	}
	size_t end3 = clock();
	cout << "set find:" << end3 - begin3 << endl;

	size_t begin4 = clock();
	for (auto e : v)
	{
		us.find(e);
	}
	size_t end4 = clock();
	cout << "unordered_set find:" << end4 - begin4 << endl << endl;

	cout <<"插入数据个数:"<< s.size() << endl;
	cout <<"插入数据个数:" << us.size() << endl << endl;;

	size_t begin5 = clock();
	for (auto e : v)
	{
		s.erase(e);
	}
	size_t end5 = clock();
	cout << "set erase:" << end5 - begin5 << endl;

	size_t begin6 = clock();
	for (auto e : v)
	{
		us.erase(e);
	}
	size_t end6 = clock();
	cout << "unordered_set erase:" << end6 - begin6 << endl << endl;
}

运行结果:

总结:有大量重复数据的时候unordered_set、unordered_map更占优势,但是有序的数据set、map更占优势。

二、unordered_set和unordered_map的OJ题目

在长度2N的数组里找出重复N次的元素

思路:把其放到unordered_map里面去,然后统计次数,算出n的一半,然后找到那个出现次数为一半的元素

cpp 复制代码
class Solution 
{
public:
	int repeatedNTimes(vector<int>& nums) 
	{
		unordered_map<int, int> countmap;
		for (auto element : nums)
		{
			countmap[element]++;
		}
		int count = nums.size() / 2;
		for (auto element : countmap)
		{
			if (element.second == count)
			{
				return element.first;
			}
		}
		//不可能的情况返回-1
		return -1;
	}
};
相关推荐
Rock_yzh1 小时前
LeetCode算法刷题——54. 螺旋矩阵
数据结构·c++·学习·算法·leetcode·职场和发展·矩阵
shx66661 小时前
2.1.2 ROS2 C++ 示例
c++·ros2
papership1 小时前
【入门级-算法-5、数值处理算法:高精度整数除以单精度整数的商和余数】
算法
lightqjx1 小时前
【C++】对set和map的使用
开发语言·数据结构·c++·stl
快乐zbc1 小时前
C++ 中 typedef 指针别名与 const 的坑
开发语言·c++
CoderYanger1 小时前
C.滑动窗口-求子数组个数-越短越合法——3258. 统计满足 K 约束的子字符串数量 I
java·开发语言·算法·leetcode·1024程序员节
2301_807997382 小时前
代码随想录-day56
算法
AI科技星2 小时前
时空运动的几何约束:张祥前统一场论中圆柱螺旋运动光速不变性的严格数学证明与物理诠释
服务器·数据结构·人工智能·python·科技·算法·生活
azoo2 小时前
cv::Mat 取元素引起的报错
c++·opencv·计算机视觉