set集合容器
set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的数据结构, 在 插入元素时, 它会自动调整二叉树的排列, 把该元素放到适当的位置, 以确保每个子树根节点的键值大于左子树的所有节点的键值, 而小于右子树所有节点的键值; 另外, 还得确保根节点左子树的高度与右子树的高度相等, 这样, 二叉树的高度最小, 从而检索速度最快. 要注意的是, 它不会重复插入相同键值的元素, 而采取忽略处理.
 
平衡二叉检索树的检索使用中序遍历算法, 检索效率高于vector, deque和list等容器.另外, 采用中序遍历算法可将键值由小到大遍历出来, 所以, 可以理解为平衡二叉检索树在插入元素时, 就会自动将元素按键值由小到大的顺序排列.
 
对于set容器中的键值, 不可直接去修改. 因为如果把容器中的一个键值修改了, set容器会根据新的键值旋转子树, 以保持新的平衡,这样, 修改的键值很可能就不在原先那个位置上了, 换句话来说, 构造set集合的主要目的就是为了快速检索
 
multiset(多重集合容器), map(映照容器)和multimap(多重映照容器)的内部结构也是平衡二叉检索树.
使用set前, 需要在程序的头文件中包含声明"#include<set>"(包含了set和multiset两种容器的定义)
 
1.1创建set集合对象
创建set对象时, 需要指定元素的类型, 这一点与其他容器一样.
#include<set>
using namespace std;
 
int main()
{
    //定义元素类型为int的集合对象s, 当前没有任何元素
    //元素的排列采用默认的比较规则, 当然, 可以自定义比较规则函数
    set<int> s;
    return 0;
}
 
1.2元素的插入与中序遍历
采用insert()方法把元素插入到集合中去, 插入的具体规则在默认的比较规则下, 是按元素值由小到大插入, 如果自己指定了比较规则函数, 则按自定义的函数插入
使用前向迭代器对集合中序遍历, 其结果正好是元素排序的结果
下面这个例子说明了insert()方法的使用方法:
#include<set>
#include<iostream>
using namespace std;
 
int main()
{
    //定义元素类型为int的集合对象s, 当前没有任何元素
    set<int> s;
    //插入了5个元素, 但由于8有重复, 第二次插入的8并没有执行
    s.insert(8);
    s.insert(1);
    s.insert(12);
    s.insert(6);
    s.insert(8);//第二次插入8, 重复元素, 不会插入
    //中序遍历集合中的元素
    set<int>::iterator it;//定义前向迭代器
    //中序遍历集合中的所有元素
    for(it = s.begin(); it != s.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
    return 0;
}
/*
1 6 8 12
*/
 
1.3元素的反向遍历
使用反向迭代器reverse_iterator可以反向遍历集合, 输出的结果正好是集合元素的反向排序结果. 它需要用到rbegin()和rend()两个方法, 他们分别给出了反向遍历的开始位置和结束位置.
集合进行反向遍历的例子:
#include<set>
#include<iostream>
using namespace std;
 
int main()
{
    //定义元素类型为int的集合对象s, 当前没有任何元素
    set<int> s;
    //插入了5个元素, 但由于8有重复, 第二次插入的8并没有执行
    s.insert(8);
    s.insert(1);
    s.insert(12);
    s.insert(6);
    s.insert(8);
    //反向遍历集合中的元素
    set<int>::reverse_iterator rit;//定义反向迭代器
    for(rit = s.rbegin(); rit != s.rend(); rit++)
    {
        cout << *rit << " ";
    }
    cout << endl;
    return 0;
}
/*
12 8 6 1
*/
 
1.4元素的删除
与插入元素的处理一样, 集合具有高效的删除处理功能, 并自动重新调整内部的红黑树的平衡.
删除的对象可以是某个迭代器位置上的元素, 等于某键值的元素, 一个区间上的元素和清空集合
#include<set>
#include<iostream>
using namespace std;
 
int main()
{
    //定义元素类型为int的集合对象s, 当前没有任何元素
    set<int> s;
    //插入了5个元素, 但由于8有重复, 第二个8并没有执行
    s.insert(8);
    s.insert(1);
    s.insert(12);
    s.insert(6);
    s.insert(8);
    //删除键值为6的那元素
    s.erase(6);
    //反向遍历集合中的元素
    set<int>::reverse_iterator rit;//定义反向迭代器
    for(rit = s.rbegin(); rit != s.rend(); rit++)
    {
        cout << *rit << " ";
    }
    cout << endl;
    //清空集合
    s.clear();
    //输出集合的大小
    cout << s.size() << endl;
    return 0;
}
/*
12 8 1
0
*/
 
1.5元素的检索
使用find()方法对集合进行检索, 如果找到查找的键值, 则返回该键值的迭代器位置, 否则, 返回集合最后一个元素后面的一个位置, 即end().
使用find()方法对集合进行检索:
#include<set>
#include<iostream>
using namespace std;
 
int main()
{
    set<int> s;
    s.insert(8);
    s.insert(1);
    s.insert(12);
    s.insert(6);
    s.insert(8);
    set<int>::iterator it; //定义前向迭代器
    //查找键值为6的元素
    it = s.find(6);
    if(it != s.end()) //找到
        cout << *it << endl;
    else    //没找到
        cout << "Not Found!" << endl;
    //查找键值为20的元素
    it = s.find(20);
    if(it != s.end()) //找到
        cout << *it << endl;
    else    //没找到
        cout << "Not Found!" << endl;
    return 0;
}
/*
6
Not Found!
*/
 
1.6自定义比较函数
使用insert()将元素插入到集合中去的时候, 集合会根据设定的比较函数将该元素放到该放的结点上去. 在定义集合的时候, 如果没有指定比较函数, 那么采用默认的比较函数, 即按键值由小到大的顺序插入元素. 在很多情况下, 需要自己编写比较函数.
编写比较函数有两种方法
(1)如果元素不是结构体, 那么, 可以编写比较函数. 下面这个程序编写的比较规则是要求按键值由大到小的顺序将元素插入到集合中:
#include<set>
#include<iostream>
using namespace std;
 
//自定义比较函数myComp, 重载"()"操作符
struct myComp
{
    bool operator() (const int &a, const int &b)
    {
        if(a != b)
            return a > b;
        else
            return a > b;
    }
};
 
int main()
{
    //定义元素类型为int的集合对象s, 当前没有任何元素
    //采用的比较函数是myComp
    set<int, myComp> s;
    //插入5个元素
    s.insert(8);
    s.insert(1);
    s.insert(12);
    s.insert(6);
    s.insert(8);
    set<int, myComp>::iterator it; //定义前向迭代器
    for(it = s.begin(); it != s.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
    return 0;
}
 
/*
12 8 6 1
*/
 
(2)如果元素是结构体, 那么, 可以直接把比较函数写在结构体内. 例如:
#include<set>
#include<string>
#include<iostream>
using namespace std;
 
struct Info
{
    string name;
    float score;
    //重载"<"操作符, 自定义排序规则
    bool operator < (const Info &a) const
    {
        //按score由小到大排列, 使用">"号即可.
        return a.score < score;
    }
};
 
int main()
{
    //定义元素类型为Info结构体的集合对象s, 当前没有任何元素
    set<Info> s;
    //定义Info类型的元素
    Info info;
    //插入3个元素
    info.name = "Jack";
    info.score = 80.5;
    s.insert(info);
    info.name = "Tomi";
    info.score = 20.5;
    s.insert(info);
    info.name = "Nacy";
    info.score = 60.5;
    s.insert(info);
    set<Info>::iterator it; //定义前向迭代器
    for(it = s.begin(); it != s.end(); it++)
    {
        cout << (*it).name << " : " << (*it).score << endl;
    }
    return 0;
}
 
/*
Jack : 80.5
Nacy : 60.5
Tomi : 20.5
*/

C++STL之set集合容器的更多相关文章

  1. 【STL】 set集合容器常用用法

    set集合容器:实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值:另外,还 ...

  2. STL之set集合容器 【转】

    set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的的数据结构,在插入元素时,它会自动调整二叉树的排列,把该元素放到适当的位置,以确保每个子树根节点的键值大于左子树所有节点的键 ...

  3. stl之set集合容器应用基础

    set集合容器使用一种称为红黑树(Red-Black Tree) 的平衡二叉检索树的数据结构,来组织泛化的元素数据.每一个节点包括一个取值红色或黑色的颜色域.以利于进行树的平衡处理.作为节点键值的元素 ...

  4. multiset多重集合容器(常用的使用方法总结)

    关于C++STL中multiset集合容器的学习,看别人的代码一百遍,不如自己动手写一遍. multiset多重集合容器和set集合容器的使用方法大多相同,不同的是multiset多重集合容器允许重复 ...

  5. set集合容器(常用的使用方法总结)

     关于C++STL中set集合容器的学习,看别人的代码一百遍,不如自己动手写一遍. 构造set集合容器的目的是为了去重+排序+快速搜索.由于set集合容器实现了红黑树多的平衡二叉检索树的数据结构,在插 ...

  6. C++ STL set集合容器

    汇总了一些set的常用语句,部分参考了这篇:http://blog.163.com/jackie_howe/blog/static/199491347201231691525484/ #include ...

  7. STL中的set集合容器进行集合运算:并、交、差实例

    集合容器的集合运算:并.交.差: #include "stdafx.h" #include <iostream> #include <set> #inclu ...

  8. C++STL之multiset多重集合容器

    multiset多重集合容器 multiset与set一样, 也是使用红黑树来组织元素数据的, 唯一不同的是, multiset允许重复的元素键值插入, 而set则不允许. multiset也需要声明 ...

  9. STL中的set容器的一点总结

    1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...

随机推荐

  1. uva 815之理解诡异的海平线题目之不容易

    首先题意:(这个真的令人无奈,题目都看不太明白) 网上百度了一下,就是以下意思: 给你n*m个格子,每个格子的面积是10*10米,整个区域外看作无限高的墙壁.输入每个格子的海拔高度(可能为负数),以及 ...

  2. sshd_config注释

    [root@H0f ~]# cat /etc/ssh/sshd_config #update by H0f -- # $OpenBSD: sshd_config,v // :: djm Exp $ # ...

  3. apache 与php的安装

    1 系统环境与软件   1 php5.5.6 下载链接:http://windows.php.net/download/#php-5.5 推荐 V11 x64,也就是64bit的. 2 apache2 ...

  4. spring boot——关于一个Mysql主键的问题

    问题是这样的: 我现在有一个被@Entity标记的类TimeLine,其中id为主键. TimeLineController中有一个接收post请求的add()方法,这个方法会接受客户端传来的一个表单 ...

  5. [转]how can I change default errormessage for invalid price

    本文转自:http://forums.asp.net/t/1598262.aspx?how+can+I+change+default+errormessage+for+invalid+price I ...

  6. php和c++socket通讯(基于字节流,二进制)

    研究了一下PHP和C++socket通讯,用C++作为服务器端,php作为客户端进行. socket通讯是基于协议的,因此,只要双方协议一致就行. 关于协议的选择:我看过网上大部分协议都是在应用层的协 ...

  7. The function getUserId must be used with a prefix when a default namespace is not specified 解决办法

    The function getUserId must be used with a prefix when a default namespace is not specified 解决方法: 1. ...

  8. Day3下

    少女[问题描述]你是能看到第一题的 friends呢.—— hja少女在图上开车, 她们希望把每条边分配给与其相连的点中一个并且每个点最多被分配一条边,问可能的方案数.[输入格式]第一行两个整数

  9. WHRER条件里的数据类型必须和字段数据类型一致

    首先看案例: 表中字段FPHONE_IMEI是varchar类型的,主键也建立在FPHONE_IMEI 字段上,原则上只要where条件中用到了这个字段,就会走索引,这也是建立索引的目的,可事实是这样 ...

  10. Static 用法

    1.Static关键字含意:static译文是静态的,静止的,因此使用 static 修饰符声明属于类型本身而不是属于特定对象(new创建的对象)的静态成员. 2.修饰使用范围 static 修饰符可 ...