116.STL中的set

发布时间 2023-07-23 20:46:16作者: CodeMagicianT

116.STL中的set

1.set的简介

set的中文译为集合,知名见其意,因此set容器也就具有集合的属性啦!而集合这个概念大家应该上数学课应该都是学过的哈,集合它具有确定性、互异性、无序性。当然我们这里重点记住它的互异性就OK了,那么什么是互异性呢?就是说一个集合里边是不会出现两个甚至以上相同的元素的(有我没他,有他没我),说明集合还是比较专一的哈,大家以后对待感情也要专一哦!

还有非常重要的一点就是set容器会自动地对元素进行升序排序(从小到大)

使用set时需要包含头文件:

#include<set>

2.set的定义及初始化

定义:

set<数据类型>变量名

例:

//set的定义 
set<int> s1; //定义一个储存数据类型为int的set容器s1 
set<double> s2; //定义一个储存数据类型为double的set容器s2 
set<string> s3; //定义一个储存数据类型为string的set容器s3
set<int> s4[N]; //定义一个储存数据类型为int的set数组,N为大小
set<double> s5[N]; //定义一个储存数据类型为double的set数组,N为大小

构造、拷贝、析构

操作 效果
set c 产生一个空的set/multiset,不含任何元素
set c(op) 以op为排序准则,产生一个空的set/multiset
set c1(c2) 产生某个set/multiset的副本,所有元素都被拷贝
set c(beg,end) 以区间[beg,end)内的所有元素产生一个set/multiset
set c(beg,end, op) 以op为排序准则,区间[beg,end)内的元素产生一个set/multiset
c.~set() 销毁所有元素,释放内存
set<Elem> 产生一个set,以(operator <)为排序准则
set<Elem,0p> 产生一个set,以op为排序准则

3.非变动性操作

操作 效果
c.count(val) 判断容器中是否存在val
c.size() 返回当前的元素数量
c.empty () 判断大小是否为零,等同于0 == size(),效率更高
c.max_size() 返回能容纳的元素最大数量
c1 == c2 判断c1是否等于c2
c1 != c2 判断c1是否不等于c2(等同于!(c1==c2))
c1 < c2 判断c1是否小于c2
c1 > c2 判断c1是否大于c2
c1 <= c2 判断c1是否小于等于c2(等同于!(c2<c1))
c1 >= c2 判断c1是否大于等于c2 (等同于!(c1<c2))

4.特殊的搜寻函数

sets和multisets在元素快速搜寻方面做了优化设计,提供了特殊的搜寻函数,所以应优先使用这些搜寻函数,可获得对数复杂度,而非STL的线性复杂度。比如在1000个元素搜寻,对数复杂度平均十次,而线性复杂度平均需要500次。

操作 效果
count (elem) 返回元素值为elem的个数
find(elem) 返回元素值为elem的第一个元素,如果没有返回end()
lower _bound(elem) 返回元素值为elem的第一个可安插位置,也就是元素值 >= elem的第一个元素位置
upper _bound (elem) 返回元素值为elem的最后一个可安插位置,也就是元素值 > elem 的第一个元素位置
equal_range (elem) 返回elem可安插的第一个位置和最后一个位置,也就是元素值==elem的区间

5.赋值

c1 =c2;

6.交换

操作 效果
c1.swap(c2) 将c1和c2 的元素互换
swap(c1,c2) 同上,全局函数

7.迭代器相关函数

 sets和multisets的迭代器是双向迭代器,对迭代器操作而言,所有的元素都被视为常数,可以确保你不会人为改变元素值,从而打乱既定顺序,所以无法调用变动性算法,如remove()。

操作 效果
c.begin() 返回一个随机存取迭代器,指向第一个元素
c.end() 返回一个随机存取迭代器,指向最后一个元素的下一个位置
c.rbegin() 返回一个逆向迭代器,指向逆向迭代的第一个元素
c.rend() 返回一个逆向迭代器,指向逆向迭代的最后一个元素的下一个位置

8.插入和删除数据

必须保证参数有效,迭代器必须指向有效位置,序列起点不能位于终点之后,不能从空容器删除元素。

操作 效果
c.insert(elem) 插入一个elem副本,返回新元素位置,无论插入成功与否。
c.insert(pos, elem) 安插一个elem元素副本,返回新元素位置,pos为收索起点,提升插入速度。
c.insert(beg,end) 将区间[beg,end)所有的元素安插到c,无返回值。
c.erase(elem) 删除与elem相等的所有元素,返回被移除的元素个数。
c.erase(pos) 移除迭代器pos所指位置元素,无返回值。
c.erase(beg,end) 移除区间[beg,end)所有元素,无返回值。
c.clear() 移除所有元素,将容器清空

例子:

#include<iostream>//c++标准头文件,可以使用cout,cin等标准编译用法
#include<set>//使用set需要带上这个文件
using namespace std;//命名空间,防止重名给程序带来各种隐患,使用cin,cout,map,set,vector,queue时都要使用

int main()
{
	set<int> s;//定义 

	s.insert(1);//插入元素1 
	s.insert(3);//插入元素3
	s.insert(2);//插入元素2

	cout << "现有的元素有" << endl;
	for (int c : s) //遍历set,注意set会将元素自动排序,插入的顺序是1、3、2,遍历的顺序是1、2、3  通过foreach遍历
	{
		cout << c << ' ';
	}
	cout << endl;
	cout << endl;

	s.erase(3);//删除元素3

	cout << "删除元素3后,现有的元素有" << endl;

	set<int>::iterator it;//使用迭代器
	for (it = s.begin(); it != s.end(); it++) //遍历set,注意set会将元素自动排序,插入的顺序是1、3、2,遍历的顺序是1、2、3 
	{
		cout << *it << ' ';
	}
	cout << endl;
	cout << endl;

	cout << "现在s.size()==";
	cout << s.size();
	
	cout << ",也即有" << s.size() <<"个元素";
	cout << endl;
	cout << endl;

	cout << "是否包含元素2:" << endl;
	if (s.count(2) != 0)
	{
		cout << "包含元素2,个数为:" << s.count(2) << endl;;
	}
	else
	{
		cout << "不包含元素2" << endl;
	}
	cout << endl;

	if (s.count(3) != 0)
	{
		cout << "包含元素3,个数为:" << s.count(3) << endl;;
	}
	else
	{
		cout << "不包含元素3" << endl;
	}
	cout << endl;

	cout << "s是否是空的:" << endl;
	if (s.empty())
	{
		cout << "即s为空" << endl;;
	}
	else
	{
		cout << "即s不为空" << endl;
	}
	cout << endl;

	s.clear();//清空集合 

	cout << "s是否是空的:" << endl;
	if (s.empty())
	{
		cout << "即s为空" << endl;;
	}
	else
	{
		cout << "即s不为空" << endl;
	}
	cout << endl;

	cout << "s是否是空的:" << endl;
	if (s.size() == 0)//s.size()==0也可以判断集合是否为空,为了考虑代码可读性,一般不用size()代替empty() 
	{
		cout << "s为空" << endl;;
	}
	else
	{
		cout << "即s不为空" << endl;
	}
	cout << endl;

	return 0;
}

输出:

现有的元素有
1 2 3

删除元素3后,现有的元素有
1 2

现在s.size()==2,也即有2个元素

是否包含元素2:
包含元素2,个数为:1

不包含元素3

s是否是空的:
即s不为空

s是否是空的:
即s为空

s是否是空的:
s为空

例子2:

// cont/set1.cpp
#include <iostream>
#include <set>
using namespace std;

int main()
{
    /*type of the collection:
     *-no duplicates
     *-elements are integral values
     *-descending order
     */
    typedef set<int, greater<int> > IntSet;

    IntSet coll1;         // empty set container

    //insert elements in random order
    coll1.insert(4);
    coll1.insert(3);
    coll1.insert(5);
    coll1.insert(1);
    coll1.insert(6);
    coll1.insert(2);
    coll1.insert(5);

    //iterate over all elements and print them
    IntSet::iterator pos;
    for (pos = coll1.begin(); pos != coll1.end(); ++pos) 
    {
        cout << *pos << ' ';
    }
    cout << endl;

    //insert 4 again and process return value
    pair<IntSet::iterator, bool> status = coll1.insert(4);
    if (status.second)
    {
        cout << "4 inserted as element "
            << distance(coll1.begin(), status.first) + 1
            << endl;
    }
    else 
    {
        cout << "4 already exists" << endl;
    }

    //assign elements to another set with ascending order
    set<int> coll2(coll1.begin(), coll1.end());

    //print all elements of the copy
    copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    //remove all elements up to element with value 3
    coll2.erase(coll2.begin(), coll2.find(3));

    //remove all elements with value 5
    int num;
    num = coll2.erase(5);
    cout << num << " element(s) removed" << endl;

    //print all elements
    copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    return 0;
}

输出:

6 5 4 3 2 1
4 already exists
1 2 3 4 5 6
1 element(s) removed
3 4 6

参考:

【C++ STL】Set和Multiset