C++STL中set的使用策略(一)

       set是STL中一种标准关联容器。它底层使用平衡的搜索树——红黑树实现,插入删除操作时仅仅需要指针操作节点即可完成,不涉及到内存移动和拷贝,所以效率比较高。

       set,顾名思义是“集合”的意思,在set中元素都是唯一的,而且默认情况下会对元素自动进行升序排列,支持集合的交(set_intersection),差(set_difference) 并(set_union),对称差(set_symmetric_difference) 等一些集合上的操作,如果需要集合中的元素允许重复那么可以使用multiset

1. 头文件——<set>
2. 定义——set<int> q;
3. 输入(插入)——insert(x);
4. 有序输出
set<int>::iterator it;
for(it = q.begin();it != q.end();it++)
{
    cout<<*it<<endl;
}
5. 删除指定元素——erase(x);
6. 清空——clear();
7. 判空——empty();
8. 大小——size();
9. 二分查找——q.lower_bound(x);

set模板原型

template <class Key, class Compare=less<Key>, class Alloc=STL_DEFAULT_ALLOCATOR(Key) >
/*Key为元素(键值)类型 greater是从升序排序(默认),可以改为less(降序排序)*/

set容器的创建

#include <iostream>
#include <set>
#include <functional>
using namespace std;
set<int> s;
int main()
{
   set<int,greater<int> > seta; //greater<int>可以不写,默认是升序
   set<int, less<int> > setb; //创建一个降序的set,需包含头文件functional
   int a[5] = {1,2,3,4,5};
   set<int > setc(a,a+5); //数组a初始化一个set;
   set<int > setd(setc.begin(),setc.end()); //setc初始化一个set
   //上述两例均为区间初始化
   set<int > sete(setd); //拷贝构造创建set
   return 0;
}
//注意写法set<int,less<int> >或set<int,greater<int> >,如果不空格,“>>”被当作位运算可能报错

       set容器的增删改查

/*1.插入*/
#include <iostream>
#include <set>
using namespace std;
set<int >s;
void setprint(int cnt)
{
    cout << "Test output :" << cnt << ":" << endl;
    for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
        cout << *it << " ";
    puts("");
    return ;
}
int main()
{
    int cnt = 1;
    s.insert(1);
    s.insert(2);
    s.insert(5);
    setprint(cnt++);
    s.insert(2); //set只允许用一个值出现一次,要插入相同元素请用multiset
    setprint(cnt++);
    int a[4] = {11,12,13,14};
    s.insert(a,a+4); //将区间[a, a+4]里的元素插入容器
    setprint(cnt++);
    return 0;
}
/*2.删除*/
//s.erase(); 删除一个元素
//s.clear(); 删除set容器中的所有的元素
#include <iostream>
#include <set>
using namespace std;
set<int >s;
void setprint(int cnt)
{
    cout << "Test output :" << cnt << ":" << endl;
    for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
        cout << *it << " ";
    puts("");
    return ;
}
int main()
{
    int cnt = 1;
    for(int i = 1; i < 11; i++){
        s.insert(i);
    }
    setprint(cnt++);
    s.erase(9); //根据元素删除
    setprint(cnt++);
    set<int>::iterator ita = s.begin();
    set<int>::iterator itb = s.begin();
    s.erase(ita);  //删除迭代器指向位置的元素
    setprint(cnt++);
    ita = s.begin();
    itb = s.begin();
    itb++;itb++;
    s.erase(ita,itb); //删除区间[ita,itb)的元素
    setprint(cnt);
    s.clear();
    return 0;
}
/*3.修改*/
//不能直接修改容器内数据,所以只能删除某元素再插入要修改的数值。
/*4.查找*/
//s.find() 查找一个元素,如果容器中不存在该元素,返回值等于s.end()
#include <iostream>
#include <set>
using namespace std;
set<int >s;
void setprint(int cnt){
    cout << "Test output :" << cnt << ":" << endl;
    for(set<int>::iterator it = s.begin(); it!= s.end(); it++)
        cout << *it << " ";
    puts("");
    return ;
}
int main(){
    int cnt = 1;
    s.insert(1);
    s.insert(2);
    s.insert(5);
    setprint(cnt++);
    if(s.find(2) != s.end())
        cout << "2 is existent" << endl;
    else
        cout << "2 is non-existent" << endl;
    if(s.find(3) == s.end())
        cout << "3 is non-existent" << endl;
    else
        cout << "2 is existent" << endl;
    return 0;
}

       set的其他常用操作

s.lower_bound(); 返回第一个大于或等于给定关键值的元素
s.upper_bound(); 返回第一个大于给定关键值的元素
s.equal_range();返回一对定位器,分别表示 第一个大于或等于给定关键值的元素 和 第一个大于给定关键值的元素,这个返回值是一个pair类型,如果这一对定位器中哪个返回失败,就会等于s.end()
#include <iostream>
#include <set>
using namespace std;
int main(){
    set<int> s;
    s.insert(1);
    s.insert(2);
    s.insert(5);
    cout << "lower_bound & upper_bound test:" << endl;
    cout << "第一个大于或等于3的元素: " << *s.lower_bound(3) << endl;
    cout << "第一个大于或等于2的元素: " <<*s.lower_bound(2) << endl;
    cout << "第一个大于2的元素: " <<*s.upper_bound(2) << endl;
    cout << "equal_range test:" << endl;
    cout << "第一个大于或等于2的元素: " <<  *s.equal_range(2).first << endl;
    cout << "第一个大于2的元素: " << *s.equal_range(2).second << endl;
    return 0;
}
//判断元素是否在set中 & 判断set是否为空
#include <iostream>
#include <set>
#include <functional>
using namespace std;
int main(){
    set<int > s;
    if(s.empty()) cout << "容器为空" << endl;
    s.insert(1);
    if(!s.empty()) cout << "容器不为空" << endl;
    if(s.count(1)) cout << "1在容器中" << endl;
    if(!s.count(2)) cout << "2不在容器中" << endl;
    return 0;
}
//自定义比较函数
#include <iostream>
#include <set>
#include <functional>
using namespace std;
struct cmp{
    bool operator () (const int &a, const int &b){
        return a > b;
    }
};
set<int, cmp>s; //自定义排序函数构造set
void setprint(int cnt){
    cout << "Test output :" << cnt << ":" << endl;
    for(set<int,cmp>::iterator it = s.begin(); it!= s.end(); it++)
        cout << *it << " ";
    puts("");
    return ;
}
int main(){
    s.insert(1);
    s.insert(2);
    s.insert(6);
    setprint(1);
    return 0;
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏琦小虾的Binary

map 学习(上)——C++中 map 的使用

map 学习(上)——C++中 map 的使用 欠下数据结构的债,迟早是要还的…… 最近写毕业论文过程中,需要用到哈希表的数据结构,此外空闲时间在刷 Leetc...

46460
来自专栏开发 & 算法杂谈

序列中查找第二小元素

序列中查找第二小元素有很多方法,本文介绍的是采用分治的思想,自底向上,序列中两两构成一对,比较选出最小值,然后构成上一层序列,然后依次网上构造,最后,根节点就是...

9130
来自专栏C/C++基础

C++中string成员函数length()与size()和strlen()的区别

上面的代码片段获取的字符串长度均是4,看不出什么区别,那么方法一和方法二有什么区别呢?请看如下代码:

12820
来自专栏编程思想之异常处理

Java编程思想之通过异常处理错误

1.     异常分为被检查的异常和运行时异常,被检查的异常在编译时被强制要求检查。异常被用来错误报告和错误恢复,但很大一部分都是用作错误报告的。

7810
来自专栏程序员互动联盟

【答疑解惑第六讲】数组与指针区别在哪?

存在问题: 小伙伴都说指针和数组不好学,总是搞不太清楚?两者到底有啥区别? 解决方案: 很多初学者朋友总是对数组和指针模模糊糊,搞不清楚。对他们之间的联系与区...

354110
来自专栏JavaEdge

(六)-class文件结构1 什么是JVM的“无关性”?2 纵观Class文件结构

31080
来自专栏浪淘沙

Python学习总结4--字符串和编码

一、编码历史     由于计算机是美国人发明的,因此,最早只有127个字符被编码到计算机里,也就是大小写英文字母、数字和一些符号,这个编码表被称为ASCI...

14040
来自专栏debugeeker的专栏

《coredump问题原理探究》Linux x86版3.5节栈布局之-fomit-frame-pointer编译选项

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuzhina/article/detai...

8220
来自专栏Python自动化测试

python内部函数学习(九)

python提供了很多的内置函数,这些内置的函数在某些情况下,可以起到很大的作用,而不需要专门去写函数实现XX功能,直接使用内置函数就可以实现,下...

12430
来自专栏JAVA技术站

原 shell学习四运算符 原

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。

5110

扫码关注云+社区

领取腾讯云代金券