IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C++】-- STL之unordered_map/unordered_set详解 -> 正文阅读

[C++知识库]【C++】-- STL之unordered_map/unordered_set详解

目录

一、map/set和unordered_map/unordered_set的区别

二、unordered_set

1.特点?

2.构造

(1)构造一个空的?unordered_set对象

(2) 用迭代器范围构造unordered_set对象

(3) 拷贝构造一个unordered_set对象

3.容量

(1)empty( )

(2)size( )?

(3)max_size( )?

4.迭代器

(1)begin( )

(2)end( )

5.查找

(1)find( )

(2)count( )?

6.元素修改

(1)insert( )

(2)erase( )

(3)clear( )

(4)swap( )

三、?unordered_map

1.特点?

2.构造??

(1)构造一个空的unordered_map对象

(2)用迭代器范围构造unordered_set对象

(3)拷贝构造一个unordered_set对象

3.容量

(1)empty( )

(2)size( )

(3)max_size( )

4.迭代器

(1)begin( )

(2)end( )?

5.元素操作符[ ]

6.查找

(1)find( )?

(2)count( )

7.元素修改

(1)insert( )

(2)erase( )

(3)clear( )

(4)swap( )


一、map/set和unordered_map/unordered_set的区别

STL有两种容器:序列式容器和关联式容器,序列式容器vetor/lost/deque,用来存储数据。关联式容器map/set/unordered_map/unordered_set用来存储数据+查找数据。

unordered_map和unordered_set是c++里面两个提供哈希表的容器,map和set底层是红黑树,unordered_map和unordered_set的底层是哈希表(散列表),是一种映射。

对于set和unordered_set的增删查,在10000个数据、100000个数据、1000000个数据的情况下分别作了对比:

#include<iostream>
#include<vector>
#include<set>
#include<time.h>
#include<unordered_set>
using namespace std;

void test_unordered_set()
{
	vector<int> v;
	v.reserve(10000);//100000、1000000
	srand((unsigned int)time(NULL));

	for (int i = 0; i < 10000; i++)//100000、1000000
	{
		v.push_back(rand());
	}

	//插入
	set<int> s;
	size_t begin1 = clock();
	for (auto e : v)
	{
		s.insert(e);
	}
	size_t end1 = clock();

	unordered_set<int> us;
	size_t begin2 = clock();
	for (auto e : v)
	{
		us.insert(e);
	}
	size_t end2 = clock();

	cout << "set insert time:" << end1 - begin1 << endl;
	cout << "unorder_set insert time:" << end2 - begin2 << endl;

	//查找
	size_t begin3 = clock();
	for (auto e : v)
	{
		s.find(e);//set自带的查找效率是O(logn)
	}
	size_t end3 = clock();

	size_t begin4 = clock();
	for (auto e : v)
	{
		us.find(e); //unordered_set自带的查找,优点:使用哈希特性查找,效率高--O(1)
	}
	size_t end4 = clock();

	cout << "set find time:" << end3 - begin3 << endl;
	cout << "unorder_set find time:" << end4 - begin4 << endl;

	//删除
	size_t begin5 = clock();
	for (auto e : v)
	{
		s.erase(e);
	}
	size_t end5 = clock();

	size_t begin6 = clock();
	for (auto e : v)
	{
		us.erase(e);
	}
	size_t end6 = clock();

	cout << "set erase time:" << end5 - begin5 << endl;
	cout << "unorder_set erase time:" << end6 - begin6 << endl;
}

int main()
{

	test_unordered_set();

	return 0;
}

10000个数据的时间:

100000个数据的时间:

?

?1000000个数据的时间:

?

?可以看到,当数据量越大时,unordered_set相比于set所消耗的时间越少,这是因为unordered_set的底层是哈希表,增删查的效率更高。

二、?unordered_set

1.特点?

(1) unordered_map是存储<value, value>键值对的关联式容器,对value进行快速索引。
(2)在unordered_set中,元素的值同时是其键,是唯一标识,键和映射值的类型相同,键不可修改。unordered_set中的元素在容器不可修改,但是可以插入和删除元素。
(3)unordered_set中的元素不按任何特定顺序排序,而是根据其哈希值组织到存储桶中,允许直接根据value快速访问各个元素(平均时间复杂度是一定的)。
(4)unordered_set比set通过键访问单个元素的速度更快,但它通常在遍历元素子集的范围迭代方面效率较低。
(5)容器中的迭代器至少有正向迭代器。

2.构造

?有以下几种构造方式:

explicit unordered_set ( size_type n = /* see below */,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& alloc = allocator_type() );//构造空的unordered_set对象

template <class InputIterator>
         unordered_set ( InputIterator first, InputIterator last,
                         size_type n = /* see below */,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& alloc = allocator_type() );//用迭代器范围构造unordered_set对象

unordered_set ( const unordered_set& ust );//拷贝构造一个unordered_set对象

(1)构造一个空的?unordered_set对象

    unordered_set<int> us1;

向里面插入元素:

	us1.insert(2);
	us1.insert(72);
	us1.insert(6);
	us1.insert(35);
	us1.insert(291);
	us1.insert(327);

(2) 用迭代器范围构造unordered_set对象

用us1的迭代器范围构造us2:?

    unordered_set<int> us2(us1.begin(), us1.end());

(3) 拷贝构造一个unordered_set对象

?用us2拷贝构造us3:

    unordered_set<int> us3(us2);

3.容量

(1)empty( )

判断unordered_set是否为空:

cout << us3.max_size() << endl;

判断us3是否为空:?

    cout << us3.empty() << endl;//判断us3是否为空

?不为空:

(2)size( )?

返回unordered_set中的元素个数

size_type size() const noexcept;

?求us3中的元素个数:

    cout << us3.size() << endl;

?

(3)max_size( )?

返回unordered_set可存储的最大元素个数:

size_type max_size() const noexcept;

求us3最大元素个数 :

    cout << us3.max_size() << endl;

?

?

4.迭代器

(1)begin( )

返回迭代器开始:?

iterator begin() noexcept;

?返回us3迭代器开始:

    unordered_set<int>::iterator it = us3.begin();

(2)end( )

返回迭代器结尾:

iterator end() noexcept;

返回us3迭代器结尾:?

    us3.end();

?

5.查找

(1)find( )

如果找到元素就返回元素所在位置,否则返回元素结尾:

iterator find ( const key_type& k );

在us3中查找327:?

	unordered_set<int>::iterator ret = us3.find(327);
	if (ret != us3.end())
	{
		cout << "找到了" << endl;
	}
	else
	{
		cout << "没找到" << endl;
	}

?

(2)count( )?

?统计容器中值为k的元素的个数:

size_type count ( const key_type& k ) const;

?统计us3中值为291的元素的个数:

    cout << us3.count(291) << endl;

?

?

6.元素修改

(1)insert( )

pair<iterator,bool> insert ( const value_type& val );//插入元素,成功返回的pair的第二个元素为true,失败则为false
iterator insert ( const_iterator hint, const value_type& val );//返回插入元素的位置
template <class InputIterator>
    void insert ( InputIterator first, InputIterator last );//插入一段区间
void insert ( initializer_list<value_type> il );//将列表作为元素插入容器中

①插入元素?

	cout << us2.insert(568).second << endl;//不存在,插入成功
	cout << us2.insert(291).second << endl;//已存在,插入失败

?

?

?②返回插入元素的位置

    cout << *us2.insert(us3.begin(), 65) << endl;

?

③?插入一段区间

    unordered_set<int> us2;
	us2.insert(us1.begin(), us1.end());
	unordered_set<int>::iterator it = us2.begin();
	while (it != us2.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;

?

?

④将列表作为元素插入容器中

	unordered_set<string> us4;
	us4.insert({ "int", "string", "float" });
	unordered_set<string>::iterator it = us4.begin();
	while (it != us4.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;

?

(2)erase( )

?删除元素:

iterator erase ( const_iterator position );//删除position位置的元素,并返回删除元素的位置
size_type erase ( const key_type& k );//返回删除值为k的元素的个数
iterator erase ( const_iterator first, const_iterator last );//删除从first到last区间的元素,并返回删除的last元素的位置

?①删除position位置的元素,并返回删除元素的位置

	unordered_set<int> us2;
	us2.insert(us1.begin(), us1.end());
	cout << *us2.erase(us2.find(6)) << endl;

?

②?删除值为k的元素的,k存在返回1,k不存在返回0

    cout << us2.erase(72) << endl;

③?删除从first到last区间的元素,并返回删除的last元素的位置

    cout << *us2.erase(us2.find(6), us2.find(291)) << endl;

?

(3)clear( )

?删除容器中所有元素

void clear() noexcept;

?清空us2中所有元素:

    us2.clear();

(4)swap( )

?交换两个同类型容器中的元素

unordered_set<int> us1;
	us1.insert(2);
	us1.insert(72);
	us1.insert(6);
	us1.insert(35);
	us1.insert(291);
	us1.insert(327);

	unordered_set<int> us5;
	us5.insert(56);
	us5.insert(57);
	us5.insert(58);
	us5.insert(59);
	us5.insert(60);
	us5.insert(61);

	us1.swap(us5);
	
	unordered_set<int>::iterator it1 = us1.begin();
	while (it1 != us1.end())
	{
		cout << *it1 << " ";
		it1++;
	}
	cout << endl;

	unordered_set<int>::iterator it5 = us5.begin();
	while (it5 != us5.end())
	{
		cout << *it5 << " ";
		it5++;
	}
	cout << endl;

?

哈系桶和哈希策略的函数等介绍完哈希表之后才能理解。

三、?unordered_map

1.特点?

(1)unordered_map是存储<key, value>键值对的关联式容器,允许通过key快速的索引到与其对应的value。
(2)在unordered_map中,键值通常用于惟一地标识元素,而映射value是一个对象,其内容与key关联。键和映射值的类型可能不同。
(3)unordered_map没有对<kye, value>按照任何特定的顺序排序, 为了能在常数范围内找到key所对应的value,unordered_map将相同哈希值的键值对放在相同的桶中。
(4)unordered_map容器通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭代方面效率较低。
(5)unordered_map实现了直接访问操作符(operator[]),它允许使用key作为参数直接访问value。
(6)容器中的迭代器至少有正向迭代器。

2.构造??

explicit unordered_map ( size_type n = /* see below */,
                         const hasher& hf = hasher(),
                         const key_equal& eql = key_equal(),
                         const allocator_type& alloc = allocator_type() );//构造空的unordered_map对象

template <class InputIterator>
  unordered_map ( InputIterator first, InputIterator last,
                  size_type n = /* see below */,
                  const hasher& hf = hasher(),
                  const key_equal& eql = key_equal(),
                  const allocator_type& alloc = allocator_type() );//用迭代器范围构造unordered_map对象

unordered_map ( const unordered_map& ump );//拷贝构造一个unordered_map对象

(1)构造一个空的unordered_map对象

    unordered_map<string, int> um1;

向里面插入元素:

    um1.insert(make_pair<string, int>("自行车", 8));
	um1.insert(make_pair<string, int>("消防车", 1));
	um1.insert(make_pair<string, int>("洒水车", 6));
	um1.insert(make_pair<string, int>("搅拌车", 7));
	um1.insert(make_pair<string, int>("小汽车", 5));

(2)用迭代器范围构造unordered_set对象

用um1的迭代器范围构造um2:

    unordered_map<string, int> um2(um1.begin(), um1.end());

(3)拷贝构造一个unordered_set对象

用um2拷贝构造um3:

    unordered_map<string, int> um3(um2);

3.容量

(1)empty( )

判断unordered_map是否为空:?

bool empty() const noexcept;

?判断um1是否为空:?

    cout << um1.empty() << endl;

?

(2)size( )

?返回unordered_map中的元素个数:

size_type size() const noexcept;

求um1中元素的个数:

    cout << um1.size() << endl;

?

(3)max_size( )

返回?unordered_map可存储的最大元素个数:

size_type max_size() const noexcept;

求um1最大元素个数 :?

    cout << um1.max_size() << endl;

?

?

4.迭代器

(1)begin( )

返回迭代器开始:?

iterator begin() noexcept;

?返回um1迭代器开始:

    unordered_map<string, int>::iterator it = um1.begin();

(2)end( )?

返回迭代器结尾:

iterator end() noexcept;

?返回um1迭代器结尾:

    um1.end();

5.元素操作符[ ]

访问key为k的元素,如果存在就返回value的引用:?

mapped_type& operator[] ( const key_type& k );

?访问key为小汽车的元素,并返回小汽车对应的value的引用:

    cout << um1["小汽车"] << endl;

?

?

6.查找

(1)find( )?

根据k返回k所在位置的迭代器,如果没找到就返回end

iterator find ( const key_type& k );

?查找洒水车:

    cout << um1.find("洒水车")->second << endl;

(2)count( )

?统计容器中key为k的元素的个数:

size_type count ( const key_type& k ) const;

?统计um1中key为"搅拌车"的元素个数:

    cout << um1.count("搅拌车") << endl;

?

7.元素修改

(1)insert( )

pair<iterator,bool> insert ( const value_type& val );//插入元素,成功返回的pair的第二个元素为true,失败则为false
iterator insert ( const_iterator hint, const value_type& val );//返回插入元素的位置
template <class InputIterator>
    void insert ( InputIterator first, InputIterator last );//插入一段区间
void insert ( initializer_list<value_type> il );//将列表作为元素插入容器中

?①插入元素

	cout << um1.insert(make_pair<string, int>("大货车", 9)).second << endl;//不存在,插入成功
	cout << um1.insert(make_pair<string, int>("搅拌车", 1)).second << endl;//已存在,插入失败

?

??②返回插入元素的位置

    cout << um1.insert(um1.begin(), make_pair<string, int>("扫地车", 10))->second << endl;

?

③?插入一段区间?

    unordered_map<string, int> um2(um1.begin(), um1.end());
	unordered_map<string, int>::iterator it2 = um2.begin();

	while (it2 != um2.end())
	{
		cout << it2->first << ":" << it2->second << endl;
		it2++;
	}
	cout << endl;

?④将列表作为元素插入容器中

    unordered_map<string, int> um3;    
    um3.insert({ { "摩托车",3 }, { "电动车",7 }});
	unordered_map<string, int>::iterator it3 = um3.begin();
	while (it3 != um3.end())
	{
		cout << it3->first << ":" << it3->second << endl;
		it3++;
	}
	cout << endl;

?

?

(2)erase( )

??删除元素:

iterator erase ( const_iterator position );//删除position位置的元素,并返回删除元素的位置
size_type erase ( const key_type& k );//返回删除值为k的元素的个数
iterator erase ( const_iterator first, const_iterator last );//删除从first到last区间的元素,并返回删除的last元素的位置

?①删除position位置的元素,并返回删除元素的位置

删除搅拌车:?

    cout << um1.erase(um1.find("搅拌车"))->first << endl;

?

②?删除值为k的元素的,k存在返回1,k不存在返回0:

    cout << um1.erase("自行车") << endl;

?

③?删除从first到last区间的元素,并返回删除的last元素的位置?

?

    cout << um1.erase(um1.find("消防车"), um1.find("扫地车"))->first << endl;

?

(3)clear( )

清空所有元素:?

void clear() noexcept;

?清空um1中所有元素:

    um1.clear();

(4)swap( )

交换两个同类型容器中的元素:

	unordered_map<string, string> um4;
	um4.insert(make_pair<string, string>("spring", "春天"));
	um4.insert(make_pair<string, string>("summer", "夏天"));
	um4.insert(make_pair<string, string>("autumn", "秋天"));
	um4.insert(make_pair<string, string>("winter", "冬天"));

	unordered_map<string, string> um5;
	um5.insert(make_pair<string, string>("east", "东"));
	um5.insert(make_pair<string, string>("south", "南"));
	um5.insert(make_pair<string, string>("west", "西"));
	um5.insert(make_pair<string, string>("north", "北"));

	um4.swap(um5);

	unordered_map<string, string>::iterator it4 = um4.begin();
	while (it4 != um4.end())
	{
		cout << it4->first << ":" << it4->second << endl;
		it4++;
	}
	cout << endl;

	unordered_map<string, string>::iterator it5 = um5.begin();
	while (it5 != um5.end())
	{
		cout << it5->first << ":" << it5->second << endl;
		it5++;
	}
	cout << endl;

?

?

?系桶和哈希策略的函数等介绍完哈希表之后才能理解。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 01:47:57  更:2022-09-15 01:49:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:16:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码