C++ STL中set和multiset的使用方法

本文深入解析C++中set容器的构造、元素插入、遍历、删除、检索、状态获取以及集合交并差等核心操作,详细阐述了如何高效地使用set容器进行数据管理和操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

容器set封装了集合的数据结构及操作。该容器实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树的根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值;另外,还得保证根节点左子树的高度与右子树高度相等。平衡二叉检索树使用中序遍历算法,检索效率高于vectordequelist等容器,另外使用中序遍历可将键值按照从小到大遍历出来。

构造set集合主要目的是为了快速检索,不可直接去修改键值。

需要引用头文件:

#include <set>

1.1 定义

template <class Key,

classCompare=less<Key>,

classAlloc=STL_DEFAULT_ALLOCATOR(Key) >

       比较函数对象及内存分配器采用的是默认参数,因此如果未指定,它们将采用系统默认方式。

       key的类型T为类或struct时,需要提供T==<的重载运算符。

struct IPLess {

public:

             bool operator() (const char *s1, const char *s2)const {

                  return strcmp(s1, s2) < 0;

             }

};

class IP {

int d1, d2, d3, d4;

public:

       booloperator<(const IP& a) const {

              return (d1 < a.d1)|| (d2 < a.d2) || (d3 < a.d3) || (d4 < a.d4);

       }

       booloperator==(const IP& a, const IP& b) const {

              return(a.d1==b.d1)&&(a.d2 == b.d2)&&(a.d3 == b.d3)&&(a.d4 == b.d4);

       }

}

 

    创建set对象,有几种常用方式:

    //创建空的set对象,元素类型为int

    set<int> setInt;

    //创建空的set对象,元素类型char*,比较函数对象(即排序准则)为自定义strLess

    set<IP, IPComp> setIP;

    //利用set对象s1,拷贝生成set对象s2

    set<int>setInt2(setInt);

    //用迭代区间[&first,&last)所指的元素,创建一个set对象

    int iArray[] = {13, 32,19};

    set<int> setInt3(iArray,iArray + 3);

    //用迭代区间[&first,&last)所指的元素,及比较函数对象strLess,创建一个set对象

    IP szArray[] = {IP(1,1,1,1), IP(2,2,2,2), IP(3,3,3,3)};

    set<IP, IPComp> setIP(szArray, szArray + 3);

 

1.2 元素插入

       使用insert函数插入数据,insert可返回pair<iterator, bool>,如果集合已有该数据,则失败并置返回值中boolfalse;否则,booltrueiterator指向刚插入数据的位置。Insert还可以一次插入[first, last)区间的多个数据,其中,first,last均为迭代器。

    set<IP, IPComp> setIP;

    setIP.insert(IP(1,1,1,1));

    setIP.insert(IP(2,2,2,2));

    setIP.insert(IP(3,3,3,3));

    setIP.insert(IP(4,4,4,4));

    pair<set<IP, IPComp>::iterator, bool> insert_Res;

    insert_Res = setIP.insert(IP(4,4,4,4));

    if(!insert_Res.second){

        cout<< "InsertFailed."<< endl;

    }

 

   IP ipArr[] = {IP(100,100,100,100), IP(101,101,101,101), IP(102,102,102,102)};

   setIP.insert(ipArr,ipArr+3);

 

1.3 元素遍历

    正向遍历(以key的升序遍历,对应树的中序遍历)

    for(set<IP, IPComp>::iterator itr = setIP.begin(); itr !=setIP.end(); itr++){

        cout<< itr->d1;

}

1.4 元素删除

与插入一样,可以高效的删除,并自动调整使红黑树平衡。
set<int> s;

s.erase(2);       //删除键值为2的元素
s.clear();

s.erase(itrFound);//itrFoundsetiterator,删除迭代器所指元素,无返回值

 

1.5 元素检索

find(),若找到,返回该键值迭代器的位置,否则,返回最后一个元素后面一个位置。
set<int> s;

set<int>::iterator it =s.find(5);    //查找键值为5的元素
if(
it!=s.end())    //找到
    cout<<*it<<endl;

else           //未找到
    cout<<"
未找到";

1.6 状态获取

set<int> s;

s.empty();//判断是否为空

s.size(); //获取元素个数

 

1.7 集合交并差

#include <algorithm>后就可以使用STL提供的集合运算函数。

求A,B交集:set_intersection

求A,B并集:set_union

求A,B差集:set_difference

求A,B对称差:set_symmetric_difference

以上四个函数参数完全一样。以set_intersection为例,讲解这几个函数的参数。

 

元素类型本身就带<操作符

template<class _InIt1,class _InIt2,class _OutIt>

_OutIt set_intersection(

    _InIt1 _First1,_InIt1 _Last1,

   _InIt2 _First2, _InIt2 _Last2,

    _OutIt _Dest

    )

元素类型本身不带<操作符,通过函数对象来实现比较的

template<class _InIt1,class _InIt2,class _OutIt, class_Pred>

_OutIt set_intersection(

    _InIt1 _First1,_InIt1 _Last1,

   _InIt2 _First2, _InIt2 _Last2,

    _OutIt _Dest

    _Pred _pre

    )

 

set<IP> setIP;

    setIP.insert(IP(1,1,1,1));

    setIP.insert(IP(2,2,2,2));

    setIP.insert(IP(3,3,3,3));

    setIP.insert(IP(4,4,4,4));

       

    set<IP> setIP2;

    setIP2.insert(IP(1,1,1,1));

    setIP2.insert(IP(2,2,2,2));

    setIP2.insert(IP(91,91,91,91));

    setIP2.insert(IP(92,92,92,92));

 

    IP arr[10];

 

    cout<< "setIP:" << endl;

    for(set<IP,IPComp>::iterator itr=setIP.begin();itr!=setIP.end();itr++){

        cout<<itr->d1<<"."<<itr->d2<<"."<<itr->d3<<"."<<itr->d4<<endl;

    }

 

    cout<< "setIP2:" << endl;

    for(set<IP,IPComp>::iterator itr=setIP2.begin();itr!=setIP2.end();itr++){

        cout<<itr->d1<<"."<<itr->d2<<"."<<itr->d3<<"."<<itr->d4<<endl;

    }

 

 

    IP* endArr =set_intersection(setIP.begin(), setIP.end(), setIP2.begin(), setIP2.end(),arr);

    int sizeArr = endArr -arr;

    cout<< "set_intersection(setIP,setIP2):"<< endl;

    for(int i = 0; i <sizeArr; i ++) {

        cout<<arr[i].d1<<"."<<arr[i].d2<<"."<<arr[i].d3<<"."<<arr[i].d4<<endl;

    }

   

    endArr= set_union(setIP.begin(), setIP.end(), setIP2.begin(), setIP2.end(), arr);

    sizeArr= endArr - arr;

    cout<< "set_union(setIP,setIP2):"<< endl;

    for(int i = 0; i <sizeArr; i ++) {

        cout<<arr[i].d1<<"."<<arr[i].d2<<"."<<arr[i].d3<<"."<<arr[i].d4<<endl;

    }

   

    endArr=set_difference(setIP.begin(),setIP.end(),setIP2.begin(), setIP2.end(), arr);

    sizeArr= endArr - arr;

    cout<< "set_difference(setIP,setIP2):"<< endl;

    for(int i = 0; i < sizeArr;i ++) {

        cout<<arr[i].d1<<"."<<arr[i].d2<<"."<<arr[i].d3<<"."<<arr[i].d4<<endl;

    }

 

    endArr= set_symmetric_difference(setIP.begin(), setIP.end(), setIP2.begin(),setIP2.end(), arr);

    sizeArr= endArr - arr;

    cout<< "set_symmetric_difference(setIP,setIP2):"<< endl;

    for(int i = 0; i <sizeArr; i ++) {

        cout<<arr[i].d1<<"."<<arr[i].d2<<"."<<arr[i].d3<<"."<<arr[i].d4<<endl;

}

 

输出结果为:

setIP:

1.1.1.1

2.2.2.2

3.3.3.3

4.4.4.4

setIP2:

1.1.1.1

2.2.2.2

91.91.91.91

92.92.92.92

set_intersection(setIP,setIP2):

1.1.1.1

2.2.2.2

set_union(setIP,setIP2):

1.1.1.1

2.2.2.2

3.3.3.3

4.4.4.4

91.91.91.91

92.92.92.92

set_difference(setIP,setIP2):

3.3.3.3

4.4.4.4

set_symmetric_difference(setIP,setIP2):

3.3.3.3

4.4.4.4

91.91.91.91

92.92.92.92

 

如果需要通过函数对象来提供IP的<运算符,如函数对象的类为IPComp,则需要在各函数最末尾增加一个参数,传递IPComp的对象。如集合交函数应为

set_intersection(setIP.begin(),setIP.end(), setIP2.begin(), setIP2.end(),

arr,IPComp());

 

 

1.8 multiset与set的差异

multiset和set的方法使用基本相同,只有少数区别:

multiset的允许一个集合中,出现多个相同的元素,而set中的元素具有唯一性,相同是在操作符==比较的意义上。

 

  •  count

set:有元素匹配,返回1;否则,返回0。

multiset:返回multiset 中其键与指定为参数的键匹配的元素数量。

 

  •  setA.erase(element);

set:删除集合中的唯一的值为element的元素;

multiset:删除集合中的所有值为element的元素。

 

  •  setA.erase(iteratorA);

都只是删除iteratorA指向的单个元素

 

 

  • find

set:返回唯一匹配元素的位置

multiset:返回第一个匹配元素的位置

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值