26.set,multiset 及 unordered_set,unordered_multiset

1.set

2.multiset

3.unordered_set

4.unordered_multiset

关联式容器

关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是'<'key, value'>'结构的键值对,在数据检索时比序列式容器效率更高。

STL中的部分容器,比如:vector、list、deque、forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。

STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的底层实现是使用平衡搜索树(即红黑树),并且容器中的元素是一个有序的序列。

set

#include

set特点

1.key和value都能唯一标识元素

2.set中的元素不可以重复(因此可以使用set去重)

扫描二维码关注公众号,回复: 10687045 查看本文章

3.set中的元素不能在容器中修改,只能删除和插入

4.set容器通过key访问单个元素的速度通常比unordered_set容器慢,set不能通过[key]访问值,set没有重载[]运算符

5.与map/multimap不同,map/multimap中存储的是真正的键值对<key,value>,set中只放value,但在底层实际存放的是由<value, value>构成的键值对。

set用法

#include

set定义及初始化

1.用初始化列表来初始化 set 容器:

    set<int> se = {1, 7, 5, 6, 9, 3, 4, 0, 2};
    set<int, greater<int>> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };  //加greater<int>后set降序

2.用集合初始化集合

    set<int> a; // 定义一个int类型的集合a
    set<int> b(a); // 定义并用集合a初始化集合b
    set<int> b(a.begin(), a.end()); // 将集合a中的所有元素作为集合b的初始值

3.list a(n, n + x); // 将数组n的前x个元素作为集合a的初值

    int array[] = { 1, 3, 5, 7, 9, 2};
    set<int> s(array, array+sizeof(array)/sizeof(array));

插入

    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
    se.insert(7);  //插入失败,set中的元素不可以重复(其实因为set元素的键值对key和value值相同, 如果完全相同的元素重复没有任何意义,而且会造成数据冗余)
    se.insert(8);  //插入成功

删除

    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
    
    //删除指定值得元素, 返回值是删除值为x的元素的个数
    se.erase(7);
    
    
    //删除迭代器所迭代的元素
    set<int>::iterator pos = find(se.begin(), se.end(), 5);
    se.erase(pos);
    
    
    //删除迭代器区间上的元素, 左闭右开[pos1, pos2)
    set<int>::iterator pos1 = find(se.begin(), se.end(), 1);
    set<int>::iterator pos2 = find(se.begin(), se.end(), 4);
    se.erase(pos1, pos2);

求容量及判空

    //求容量
    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
    cout << se.size() << endl;
    
    
    //判空
    set<int> se1;
    cout << se.empty() << endl;  //返回值0 非空
    cout << se1.empty() << endl;  //返回值1 空

清空

    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
    se.clear();
    cout << se.empty() << endl;

交换

    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
    set<int> se2 = {8, 9, 11, 15, 32, 64, 128};
    cout << se.size() << endl;
    
    se2.swap(se);
    
    for (const auto& e : se)
    	cout << e << " ";
    cout << endl;
    //se: 8 9 11 15 32 64 128
    
    for (const auto& e : se2)
    	cout << e << " ";
    cout << endl;
    //se2: 0 1 2 3 4 5 6 7 9

遍历

1.利用C++ auto

(1).不加const

    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
    for (auto& e : se)
    		cout << e << " ";
    	cout << endl;

由于set不允许修改元素,因此无论是否是反向迭代器或者常迭代器,都不能修改set

(1).加const

    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
    for (const auto& e : se)
    		cout << e << " ";
    	cout << endl;

auto关键字遍历的话,如果给auto关键字前面加上const,for (const auto e : people) 那么就无法通过e来修改值了

2.利用迭代器

(1).正向迭代器
map<string, size_t>::iterator

    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
    set<int>::iterator it = se.begin();  //或者: auto it = se.begin();
    	while(it != se.end())
    	{
    		cout<<*it<<" ";
    		++it;
    	}
	

(2).正向常迭代器
map<string, size_t>::const_iterator

    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
	set<int>::const_iterator it = se.cbegin();  //或者: auto it = se.begin();
	while (it != se.cend())
	{
		cout << *it << " ";
		++it;
	}
	

(3).反向迭代器
map<string, size_t>::reverse_iterator

    set<int>::reverse_iterator it = se.rbegin();  //或者: auto it = se.begin();
	while (it != se.rend())
	{
		cout << *it << " ";
		++it;
	}

(4).反向常迭代器
map<string, size_t>::const_reverse_iterator

    set<int>::const_reverse_iterator it = se.crbegin();  //或者: auto it = se.begin();
	while (it != se.crend())
	{
		cout << *it << " ";
		++it;
	}

查找 时间复杂度为:

log_2 n
    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
    set<int>::iterator pos = find(se.begin(), se.end(), 5);
    

multiset

#include

multiset特点(与set的区别是)

1.multiset中的元素可以重复,set是中value是唯一的

    multiset<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
	se.insert(7);
	multiset<int>::iterator it = se.begin();
	while (it != se.end())
		cout << *it++;
	cout << endl;
	//输出: 0123456779

2.multiset容器通过key访问单个元素的速度通常比比unordered_multiset容器慢

multiset用法与set相似

插入 容量及判空 清空 交换相似

删除与set不同:

删除指定值的元素, 返回值是删除值为x的元素的个数

    multiset<int> multise = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
	multise.insert(7);
    int erasenum = multise.erase(7);  //返回删除值为x的元素的个数
	cout << "erase(7)"<< erasenum <<"个"<<endl;

与set查找不同:

    multiset<int> multise = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
	multiset<int>::iterator mulit = multise.find(7);

unordered_set

#include<unordered_set>

unordered_set特点

1.无序

int arr[] = {5, 4, 3, 1, 7, 4, 9, 0};
	unordered_set<int> unorderse(arr, arr+ sizeof(arr)/sizeof(int));
	unordered_set<int>::iterator uorit = unorderse.begin();
	while (uorit != unorderse.end())
		cout << *uorit++;
	cout << endl;
    //输出:5439170	

2.元素不重复

	unorderse.insert(10);
	unorderse.insert(10);
	unorderse.erase(10);
	while (uorit != unorderse.end())
		cout << *uorit++;
	cout << endl;
	//out: 5439170

3.swap只能是相同set才能交换

    int arr[] = {5, 4, 3, 1, 7, 4, 9, 0};
	unordered_set<int> unorderse(arr, arr+ sizeof(arr)/sizeof(int));
    set<int> se = { 1, 7, 5, 6, 9, 3, 4, 0, 2 };
	unorderse.swap(se);  //error
unordered_set用法与set相似

插入 删除 容量及判空 清空 交换相似

与set查找不同:

    int arr[] = {5, 4, 3, 1, 7, 4, 9, 0};
	unordered_set<int> unorderse(arr, arr+ sizeof(arr)/sizeof(int));
    unordered_set<int>::iterator find = unorderse.find(10);
	cout << *find << endl;

unordered_multiset

#include

unordered_multiset特点(与multiset的区别是)

1.可以插入值相同的元素,相同值的元素会放在一块

    unordered_multiset<int> unmulset = {4, 6, 7, 8, 3, 4, 9, 10};
	unordered_multiset<int>::iterator unorderedit = unmulset.begin();

	while (unorderedit != unmulset.end())
		cout << *unorderedit++;
	cout << endl;
	//out: 4467839105
unordered_multiset用法与multiset相似

插入 删除 容量及判空 清空 交换 查找相似

发布了188 篇原创文章 · 获赞 65 · 访问量 8388

猜你喜欢

转载自blog.csdn.net/qq_43808700/article/details/105080609