set, multiset 和 unordered_set, unordered_multiset

集合(Set)是一种包含已排序对象的关联容器。 set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的数据结构,在插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,它不会插入相同键值的元素,而采取忽略处理。

平衡二叉树的检索使用中序遍历算法,检索效率高于vector、deque和list等容器。

对于set容器中的键值,不可直接去修改!应该先删除该键值,再插入新的键值。

set提供了集合的交并补运算。

头文件为#include <set>

1.创建set集合对象

set <Element> s;
Element容器中的数据类型(可以是int,double等系统自带的类型,也可以为自定义类型)

2.元素的插入和遍历

insert()插入元素

迭代器遍历

#include <iostream>
#include <set>
using namespace std;
int main()
{
	set <int> s; //建立set容器 
    s.insert(6);//插入6 
    s.insert(1);//插入1
    s.insert(9);//插入9 
    s.insert(1);//插入1 
    
    for(set<int>::iterator it = s.begin(); it != s.end(); it++)//定义前向迭代器遍历输出 
    {
    	printf("%d ",*it);
	}
	printf("\n");
	for(set<int>::reverse_iterator rit = s.rbegin(); rit != s.rend(); rit++)//定义反向迭代器遍历输出 
    {
    	printf("%d ",*rit);
	}
    return 0;
}
2.元素的删除

erase()删除函数,删除某一个元素或者某一段。

#include <iostream>
#include <set>
using namespace std;
int main()
{
	set <int> s; //建立set容器 
    s.insert(6);//插入6 
    s.insert(1);//插入1
    s.insert(9);//插入9  
    
    for(set<int>::iterator it = s.begin(); it != s.end(); it++)//定义前向迭代器遍历输出 
    {
    	printf("%d ",*it);
	}
    s.erase(9);//删除9 
    printf("\n");
    for(set<int>::iterator it = s.begin(); it != s.end(); it++)//定义前向迭代器遍历输出 
    {
    	printf("%d ",*it);
	}
	printf("\n");
    return 0;
}
3.元素的检索

find()函数查找键值,查找到就返回迭代器位置,如果查找不到返回end位置的迭代器 

count()函数判断某个元素是否存在

#include <iostream>
#include <set>
using namespace std;
int main()
{
	set <int> s; //建立set容器 
    s.insert(6);//插入6 
    s.insert(1);//插入1
    s.insert(9);//插入9  
    set<int>::iterator it;
    it=s.find(6);//查找键值6,如果查找不到返回end位置的迭代器 
    if(it != s.end())//找到了 
	    printf("%d\n",*it);
	else 
		printf("not find it\n");
//查找元素999是否存在存在返回true不存在返回fasle 
    if(s.count(999))//找到了 
	    printf("%d\n",*it);
	else 
		printf("not find it\n");
    return 0;
}

4.自定义比较函数
#include <iostream>
#include <set>
#include <functional>
using namespace std;

struct Node
{
	int a,b;
    bool operator < (const Node &A) const
	{
        return a > A.a;
    }
};
set <Node> s; //自定义排序函数构造set
int main()
{
	Node x;
	x.a = 1,x.b = 39;
    s.insert(x);
    x.a = 2,x.b = 17;
    s.insert(x);
    x.a = 3,x.b = 28;
    s.insert(x);
    for(set<Node>::iterator it = s.begin(); it != s.end(); it++)
    {
    	printf("%d %d\n",(*it).a,(*it).b);
	}
    return 0;
}

5.集合的交,并,补,差及对称差运算

这些运算在<algorithm>头文件中

假设有集合R,S。

并集:set_union(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R∪S

交集:set_intersection(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R∩S

差集:set_difference(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R-S

对称差:set_symmetric_difference(S.begin(), S.end(), R.begin(), R.end(), inserter(ans, ans.begin()));//R⊕S

假设全集U = R ∪ S,那么R对于U的补集为U - R。

#include<iostream>
#include<set>
#include<algorithm>
using namespace std;
int main()
{
    set<int> R, S, ans;
    cout << "R:";
    for (int i = 0; i <= 6; i++) { R.insert(i); cout << i << " "; }//  0 1 2 3 4 5 6
    cout << endl;
    cout << "S:";
    for (int i = 4; i <= 10; i++) { S.insert(i); cout << i << " "; }//         4 5 6 7 8 9 10
    cout << endl;

    set_union(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R∪S
    cout << "交:";
    for (auto i: ans) cout << i << " ";
    cout << endl; ans.clear();

    set_intersection(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R∩S
    cout << "并:";
    for (auto i: ans) cout << i << " ";
    cout << endl; ans.clear();

    set_difference(R.begin(), R.end(), S.begin(), S.end(), inserter(ans, ans.begin()));//R-S
    cout << "R-S:";
    for (auto i: ans) cout << i << " ";
    cout << endl; ans.clear();

    set_difference(S.begin(), S.end(), R.begin(), R.end(), inserter(ans, ans.begin()));//S-R
    cout << "S-R:";
    for (auto i: ans) cout << i << " ";
    cout << endl; ans.clear();

    set_symmetric_difference(S.begin(), S.end(), R.begin(), R.end(), inserter(ans, ans.begin()));//R⊕S
    cout << "对称差(环和):";
    for (auto i: ans) cout << i << " ";
    cout << endl; ans.clear();
    return 0;
}


多重集合容器(multiset)

基本和set一样,但是这个允许插入重复的键值!因为包含重复元素,所以,在插入元素、删除元素、查找元素上较set有差别

1.插入元素

#include <iostream>
#include <set>
using namespace std;
int main()
{
	multiset <int> ms; //建立multiset容器 
    ms.insert(6);//插入6 
    ms.insert(1);//插入1
    ms.insert(9);//插入9 
    ms.insert(1);//插入1 
    
    for(multiset<int>::iterator it = ms.begin(); it != ms.end(); it++)//定义前向迭代器遍历输出 
    {
    	printf("%d ",*it);
	}
	printf("\n");
    return 0;
}
2.删除元素

#include <iostream>
#include <set>
using namespace std;
int main()
{
	multiset <string> ms; //建立multiset容器 
    ms.insert("666");//插入666 
    ms.insert("111");//插入111
    ms.insert("abc");//插入abc 
    ms.insert("aaa");//插入aaa 
    ms.insert("111");//插入111
    
    for(multiset<string>::iterator it = ms.begin(); it != ms.end(); it++)//定义前向迭代器遍历输出 
    {
    	cout<< *it <<endl;
	}
	printf("\n");
    int n = ms.erase("111");//删除"111"所有元素,返回删除个数2 
    printf("删除元素个数为:%d\n",n);
    for(multiset<string>::iterator it = ms.begin(); it != ms.end(); it++)//定义前向迭代器遍历输出 
    {
    	cout<< *it <<endl;
	}
	printf("\n");
    return 0;
}
3.查找元素

返回符合要求的第一个元素的迭代器位置。他有lower_bound和upper_bound的两个函数。

#include <iostream>
#include <set>
using namespace std;
int main()
{
	multiset <string> ms; //建立multiset容器 
    ms.insert("666");//插入666 
    ms.insert("111");//插入111
    ms.insert("abc");//插入abc 
    ms.insert("aaa");//插入aaa 
    ms.insert("111");//插入111
    multiset<string>::iterator it;
	it=ms.find("111");//查找键值6,如果查找不到返回end位置的迭代器 
    if(it != ms.end())//找到了 
	    cout << *it << endl;
	else 
		printf("not find it\n");
		
	it=ms.find("xyz");
    if(it != ms.end())//找到了 
	    cout << *it << endl;
	else 
		printf("not find it\n");
		
	it=ms.lower_bound("111");
	if(it != ms.end())//找到了 
	    cout << *it << endl;
	else 
		printf("not find it\n");
    return 0;
}

unordered_set

unordered_set是无序的,与set相比运行较快,内存占用较大。基本操作与set相同。


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值