【C++】unordered_set和unordered_map介绍及使用【附OJ题】

【C++】unordered_set和unordered_map介绍及使用【附OJ题】_第1张图片

目录

一、unordered_set和unordered_map的介绍和使用 

1、介绍

 2、使用及与set和map的区别

3、O(logN)和 O(1)的效率对比 

二、力扣OJ题

1、重复N次的元素

2、两个数组的交集


 

一、unordered_set和unordered_map的介绍和使用 

1、介绍

 unordered_setunordered_mapc++11才引入的 

【C++】unordered_set和unordered_map介绍及使用【附OJ题】_第2张图片

【C++】unordered_set和unordered_map介绍及使用【附OJ题】_第3张图片

unordered_set 和unordered_map不支持修改(这一点和set和map一样),不然底层哈希结构就乱了,且对于数据不会自动排序,并且他不支持双向迭代器,其是单向迭代器

命名风格来看,JAVA中的unordered_set称为HashSetset称为TreeSetunordered_map称为HashMapmap称为TreeMap,因为一个底层是哈希表实现的,一个是红黑树实现的


 2、使用及与set和map的区别

使用下 unordered_setunordered_map,并对比setmap

#include
#include
#include
#include
#include
#include
using namespace std;

void test_unordered_set_map()
{
	cout << "测试unordered_set:" << endl;
	//unordered_set能去重,但不能排序
	unordered_set us;
	us.insert(4);
	us.insert(2);
	us.insert(1);
	us.insert(5);
	us.insert(6);
	us.insert(2);

	//unordered_set的迭代器遍历
	unordered_set::iterator it = us.begin();
	while (it != us.end())
	{
		//*it = 4;//报错,因为不能修改
		cout << *it << " ";
		++it;
	}
	cout << endl;

	cout << "测试set:" << endl;
	//set能去重,也能排序
	set s;
	s.insert(4);
	s.insert(2);
	s.insert(1);
	s.insert(5);
	s.insert(6);
	s.insert(2);

	//set的迭代器遍历
	set::iterator sit = s.begin();
	while (sit != s.end())
	{
		cout << *sit << " ";
		++sit;
	}
	cout << endl;

	cout << "测试unordered_map" << endl;
	unordered_map dict;
	dict.insert(make_pair("sort", "排序"));
	dict["string"] = "字符串";//第一次operator[]相当于插入操作
	dict.insert(make_pair("left", "左边"));
	unordered_map::iterator dit = dict.begin();
	while (dit != dict.end())
	{
		cout << dit->first << ":" << dit->second << endl;
		++dit;
	}

	cout << "测试map:" << endl;
	map dicts;
	dicts.insert(make_pair("sort", "排序"));
	dicts["string"] = "字符串";//第一次operator[]相当于插入操作
	dicts.insert(make_pair("left", "左边"));
	map::iterator dits = dicts.begin();
	while (dits != dicts.end())
	{
		cout << dits->first << ":" << dits->second << endl;
		++dits;
	}
}

int main()
{
	test_unordered_set_map();

	return 0;
}

运行结果如下:

【C++】unordered_set和unordered_map介绍及使用【附OJ题】_第4张图片

总结: 


 

3、O(logN)和 O(1)的效率对比 

注:O(1)是常数次,不是说的就是1次 

O(logN) O(1)差别不算大,但是累计起来就有差别了,所以这也是引入unordered_setunordered_map的原因

利用代码测试下两者的效率差异:

void test_efficiency()
{
	unordered_set us;
	set s;

	const int n = 1000000;
	vector v;
	v.reserve(n);//需要初始化,才用resize,resize是开空间+初始化,reserve是开空间
	srand((unsigned int)time(0));//设立随机数种子,使每次运行程序都产生不同的数
	for (size_t i = 0; i < n; ++i)
	{
		v.push_back(rand());//插入每次生成的随机数
	}
	//测试unordered_set insert
	size_t begin1 = clock();
	for (size_t i = 0; i < n; ++i)
	{
		us.insert(v[i]);
	}
	size_t end1 = clock();
	cout << "unordered_set insert:" << end1 - begin1 << endl;

	//测试set insert
	size_t begin2 = clock();
	for (size_t i = 0; i < n; ++i)
	{
		s.insert(v[i]);
	}
	size_t end2 = clock();
	cout << "set insert:" << end2 - begin2 << endl;

	//测试unordered_set find
	size_t begin3 = clock();
	for (size_t i = 0; i < n; ++i)
	{
		us.find(v[i]);
	}
	size_t end3 = clock();
	cout << "unordered_set find:" << end3 - begin3 << endl;

	//测试set find
	size_t begin4 = clock();
	for (size_t i = 0; i < n; ++i)
	{
		s.find(v[i]);
	}
	size_t end4 = clock();
	cout << "set find:" << end4 - begin4 << endl;
}

注:性能测试:要用release版本+多次测试取平均值

运行结果【10万个数据下】:

运行结果【100万个数据下】:

其实真实情况下unordered_set的查找效率会比set查找效率要高的 ,综合而言还是unordered_set的效率要高,进而说明了O(logN)和O(1)的效率差距


二、力扣OJ题

1、重复N次的元素

【C++】unordered_set和unordered_map介绍及使用【附OJ题】_第5张图片

【C++】unordered_set和unordered_map介绍及使用【附OJ题】_第6张图片

 思路:

这跟我们之前讲过的出现水果的次数的题差不多,利用map或unordered_map就可秒杀这道题了

class Solution {
public:
	int repeatedNTimes(vector& nums) {
		//用map或unordered_map都行
		unordered_map countMap;
		for (auto e : nums)
		{
			countMap[e]++;//利用operator[],传入key,返回对应value再++
		}

		int N = nums.size() / 2;
		for (auto& kv : countMap)
		{
			if (kv.second == N)
			{	//若出现频率为N
				return kv.first;//返回key值,即nums中的数据
			}
		}

		return -1;//若不存在,返回一个值即可
	}
}

2、两个数组的交集

【C++】unordered_set和unordered_map介绍及使用【附OJ题】_第7张图片

class Solution {
public:
	vector intersection(vector& nums1, vector& nums2) {
		//nums1和nums2的元素都要去重,不然最后结果可能出现重复数据
		
		//用unordered_set对nums1中的元素去重
		unordered_set s1;
		for (auto e : nums1)
			s1.insert(e);

		//用unordered_set对nums2中的元素去重
		unordered_set s2;
		for (auto e : nums2)
			s2.insert(e);

		//遍历s1,如果s1中某个元素在s2中出现过,即为交集
		vector ret;
		for (auto e : s1)
		{
			if (s2.find(e) != s2.end())
				ret.push_back(e);
		}

		return ret;
	}
};

你可能感兴趣的:(【c++基础】,c++,开发语言)