8

C++中STL标准容器类 SET 简单入门使用详解,SET容器类简单相关实例

 3 years ago
source link: https://blog.popkx.com/C-%E4%B8%ADSTL%E6%A0%87%E5%87%86%E5%AE%B9%E5%99%A8%E7%B1%BB-SET-%E7%AE%80%E5%8D%95%E5%85%A5%E9%97%A8%E4%BD%BF%E7%94%A8%E8%AF%A6%E8%A7%A3-SET%E5%AE%B9%E5%99%A8%E7%B1%BB%E7%AE%80%E5%8D%95%E7%9B%B8%E5%85%B3%E5%AE%9E%E4%BE%8B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

C++标准容器类STL中的集合 set 比较特殊,在其中存储的元素是独一无二的,因为它存储的元素值同时也充当“key”的角色,也即可以通过“key”访问指定的元素。此外,元素一旦被插入到 set 容器类中,就不能在被修改,不过,我们可以删除它或者插入新的元素。

STL 中的集合 set

要使用C++标准容器类 STL 中的 set,需要先包含<set>头文件:

#include <set>

之后,便可定义 set 对象:

set<data_type> myset;

其中的 data_type 可以是任意的数据类型,所谓“任意”,当然也包括 set 本身,例如下面这两行C++代码:

set<int> int_set;
set<set<int> > int_sets;

上述第一行代码定义的 int 类型的 set 容器,其中可以存储 int 型的元素。第二行代码则定义了 set<int> 类型的元素,其中可以存储 set<int> 型的元素。

操作 set

操作C++中标准容器类 set 很像操作 map(本专栏之后会讨论),下面是 set 类的一些基本操作(成员函数):

  • begin:返回指向 set 第一个元素的迭代器。
  • end:返回指向 set 最后一个元素的迭代器。
  • insert:将新元素插入 set,insert 方法一般有 3 中形式:

    • insert(elem):将 elem 直接插入到 set 中,并且重新排序。
    • insert(pos, elem):将 elem 插入到 set 中的 pos 位置。
    • insert(it.begin(), it.end()):将 it 表示范围内的元素插入到 set。
  • erase:从 set 中删除一个元素。
  • size:返回 set 中元素的数目。
  • max_size:返回 set 能够容纳的最大 size。
  • empty:返回 set 中是否有元素。
  • clear:删除 set 中的所有元素。
  • find:在 set 中查找元素,如果找到了,返回一个指向改元素的迭代器,如果找不到,返回一个指向 set.end 的迭代器。

作为实例,下面这段C++代码简单使用了上述各种方法,请看:

#include <iostream>
#include <set>
#include <iterator>
using namespace std;

int main()
{
    set <int> myset;
    
    myset.insert(140);
    myset.insert(130);
    myset.insert(160);
    myset.insert(120);
    
    cout<<"\nSize of myset: "<<myset.size();
    
    set <int > :: iterator itr;
    cout << "\nThe set myset is : ";
    for (itr = myset.begin(); itr != myset.end(); ++itr)
         cout << ' ' << *itr; 
    cout << endl;
    
    set<int>::iterator it = myset.begin();
    myset.insert(it,100);
    
    cout << "\nAfter inserting 100,the set myset is : ";
    for (itr = myset.begin(); itr != myset.end(); ++itr)
        cout << ' ' << *itr; 
    cout << endl;
    
    int arr[3] = {110,150,150};
    
    myset.insert(arr,arr+2);
    cout << "\nAfter inserting array arr,the set myset is : ";
    for (itr = myset.begin(); itr != myset.end(); ++itr)
        cout << ' ' << *itr; 
    cout << endl;
    
    cout << "\nAfter removal of elements less than 130, myset: ";
    
    myset.erase(myset.begin(), myset.find(130));
    for (itr = myset.begin(); itr != myset.end(); ++itr)
        cout << ' ' << *itr; 
    
    cout << endl;

    return 0;
}

编译并执行这段C++代码,得到如下输出:

Size of myset: 4
The set myset is :  120 130 140 160

After inserting 100,the set myset is :  100 120 130 140 160

After inserting array arr,the set myset is :  100 110 120 130 140 150 160

After removal of elements less than 130, myset:  130 140 150 160

这段C++程序一开始通过简单的 insert() 函数创建了一个 size 为 4 的 set。

接着,程序使用了另外一种形式的 insert(it,100) 函数将 100 插入到 set 中,从输出来看,元素 100 被成功插入到 set 中了,而且 set 也被重新排序了。

然后,我们又通过第三种形式的 insert(arr,arr+2) 函数插入了数组 {110,150,150}。但是从输出来看,在执行完插入后,set 中只有一个 150,这是因为 set 中的元素是独一无二的。

最后,我们通过 find() 函数查找到元素 130 在 set 中的位置,并且调用 erase() 函数将 set 开头到该位置的元素删除,也就是将小于 130 的元素删除,从结果来看,一切与预期一致。

“多元 set” multiset

从字面意思来看,multiset 可以拆分成 multi 和 set,因此 multiset 的本质是 set,而 multi 则说明了它与普通 set 不同的地方:multiset 允许内部有相同的元素

定义一个 multiset 是简单的,例如定义一个存放 int 元素的 multiset:

multiset<int> mset;

操作 multiset 的方式与普通 set 没有什么不同,下面这段C++代码是一个实例,请看:

#include <iostream>
#include <set>
#include <iterator>
using namespace std;

int main()
{
    multiset <int> myset;
    
    myset.insert(11);
    myset.insert(13);
    myset.insert(13);
    myset.insert(10);
    
    cout<<"\nSize of myset: "<<myset.size();
    
    set <int > :: iterator itr;
    cout << "\nAfter inserting four elements, the multiset myset is : ";
    for (itr = myset.begin(); itr != myset.end(); ++itr)
        cout << ' ' << *itr; 
    cout << endl;
    
    set<int>::iterator it = myset.begin();
    myset.insert(it,15);
    
    cout << "\nAfter inserting 15,the multiset myset is : ";
    for (itr = myset.begin(); itr != myset.end(); ++itr)
        cout << ' ' << *itr; 
    cout << endl;
    
    cout << "\nAfter removal of elements less than 15, myset: ";
    
    myset.erase(myset.begin(), myset.find(15));
    for (itr = myset.begin(); itr != myset.end(); ++itr)
        cout << ' ' << *itr; 
    
    cout << endl;

    return 0;
}

编译并执行这段C++代码,可得到如下输出:

Size of myset: 4
After inserting four elements, the multiset myset is :  10 11 13 13

After inserting 15,the multiset myset is :  10 11 13 13 15

After removal of elements less than 15, myset:  15

代码一开始插入了 4 个元素到 multiset,其中有两个元素是相同的。但是从最后的输出来看,multiset 不像普通 set,它允许内部存放两个相同的元素。其他过程就与 set 的实例没什么不同了。

“无序 set” unreordered_set

前面讨论了两种集合:set 和 multiset。其中,set 是一个有序的集合,并且其中的元素独一无二,也即不会有两个相同的元素。multiset 也是一个“有序”的集合,它与 set 的不同点在于其内部可以存放相同的元素。

C++中的 unreordered_set 是一个“无序”的集合容器,其中存放的元素的顺序是任意的,这一点与 set/multiset 是不同的。

类似于 map 容器类,unreordered_set 也使用了哈希表,通过 key 访问元素。作为对比,set 在其内部使用了平衡树管理元素。

使用“无序 set”,需要先包含头文件<reordered_set>,相关C++代码如下:

#include <unordered_set>

定义一个“无序 set” 是简单的,例如定义一个存放 int 元素的对象的 C++代码可以如下写:

unordered_set<int> uset;

操作 unreordered_set 的方法大都与 set 相同,下面是一段简单的C++代码实例,请看:

#include<iostream>
#include <unordered_set>
using namespace std;
 
int main()
{
    unordered_set<int> uset; 
    unordered_set<int> :: iterator it; 
    
    for(int i=0;i<5;i++){
        uset.insert(i+2); 
    }
    
    cout<<"\nSize of uset: "<<uset.size();
    cout<<endl;
    
    it= uset.begin();
    uset.insert(it,99);
    
    int ary[]= { 13, 26, 39};
    uset.insert(ary, ary+3); // Inserting using method3
    
    cout<<"\nElements in unordered set are: ";
    for(it= uset.begin(); it!=uset.end(); it++) cout << *it << " ";     
    cout<<endl;
    
    int key=13;
    if (uset.find(key) == uset.end()) 
                cout<<"\nkey = "<< key << "not found\n\n"; 
        else
                cout << "\nFound key = " << key << endl << endl;
    
    cout<<"umap bucket_count : "<<uset.bucket_count();
               cout<<"\nbucket_size : "<<uset.bucket_size(2);
    
    return 0;
}

编译并执行这段C++代码,得到如下输出:

Size of uset: 5

Elements in unordered set are: 99 39 6 5 26 4 3 13 2 

Found key = 13

umap bucket_count : 11

代码开头插入 5 个元素然后插入 4 个元素到无序 set 的操作与之前没什么不同,但是从之后的输出来看,unreordered_set 中存放的元素顺序与插入顺序并不对应,这对于内部使用哈希表管理元素的无序 set 来说并无不妥。

接着,程序调用了 find() 函数查找 key=13 是否在无序 set 中,从输出来看,程序找到了对应的结果。

最后,程序调用了之前两种 set 没有的两个函数:bucket_count() 和 bucket_size() 函数,这两个函数和 unreordered_set 内部使用的哈希映射有关。

本文主要讨论了C++标准容器类中的三种 set,它们各有特点:set 不允许自己内部有两个相同的元素,而 multiset
则可以,不过这两种序列中的所有元素都是有序的,与之对应的,unreordered_set 中的元素是无序的,其内部元素的顺序与插入顺序没有关系。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK