1. 程式人生 > 實用技巧 >c++的 set 和 multiset 容器

c++的 set 和 multiset 容器

set和multiset會根據特定的排序準則,自動將元素進行排序。不同的是後者允許元素重複而前者不允許。

需要包含標頭檔案:

#include <set>

set和multiset都是定義在std空間裡的類模板:

template<class _Kty,  
    class _Pr = less<_Kty>,  
    class _Alloc = allocator<_Kty> >  
class multiset  
template<class _Kty,  
    class _Pr = less<_Kty>,  
    
class _Alloc = allocator<_Kty> > class multiset

只要是可復賦值、可拷貝、可以根據某個排序準則進行比較的型別都可以成為它們的元素。第二個引數用來定義排序準則。預設準則less是一個仿函式,以operator<對元素進行比較。

所謂排序準則,必須定義strict weak ordering,其意義如下:

1、必須使反對稱的。

對operator<而言,如果x<y為真,則y<x為假。

2、必須使可傳遞的。

對operator<而言,如果x<y為真,且y<z為真,則x<z為真。

3、必須是非自反的。

對operator<而言,x<x永遠為假。

因為上面的這些特性,排序準則可以用於相等性檢驗,就是說,如果兩個元素都不小於對方,則它們相等。

set和multiset的功能

和所有關聯式容器類似,通常使用平衡二叉樹完成。事實上,set和multiset通常以紅黑樹實作而成。

自動排序的優點是使得搜尋元素時具有良好的效能,具有對數時間複雜度。但是造成的一個缺點就是:

不能直接改變元素值。因為這樣會打亂原有的順序。

改變元素值的方法是:先刪除舊元素,再插入新元素。

存取元素只能通過迭代器,從迭代器的角度看,元素值是常數。

操作函式

set的形式可以是:

set的程式練習:

#include<iostream>
using namespace std;
#include<set>
#include<string>
//1.集合 元素唯一 自動排序(預設情況是從小到大) 不能按照陣列的方式插入元素
//2.紅黑樹 

void main91()
{
    set<int> set1;
    for (int i = 0; i < 5; i++)
    {
        int temp = rand();
        set1.insert(temp);
    }
    //插入元素
    set1.insert(100);
    set1.insert(100);
    set1.insert(100);

    for (set<int>::iterator it = set1.begin(); it != set1.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;

    //刪除集合
    while (!set1.empty())
    {
        set<int>::iterator it = set1.begin();
        cout << *it << " ";
        set1.erase(set1.begin());
    }
    
}
//對基本的資料型別能夠自動排序
void main92()
{
    set<int> set1;
    set<int, less<int> > set2;//從小到大 set1的完整形式(預設情況下)
    set<int, greater<int> > set3;//從大到小的完整形式
    for (int i = 0; i < 5; i++)
    {
        int temp = rand();
        set3.insert(temp);
    }
    //插入元素
    set3.insert(100);
    set3.insert(100);
    set3.insert(100);
    // 遍歷  順序應是從大到小
    for (set<int, greater<int>> ::iterator it = set3.begin(); it != set3.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

//對於複雜的資料型別 Teacher Student
class Student
{
public:
    Student(const char *name, int age)
    {
        strcpy_s(this->name, name);
        this->age = age;
    }

public:
    char name[64];
    int age;

};

//仿函式
struct FuncStudent
{
    bool operator()(const Student& left, const Student& right) const //不加const報錯
    {
        if (left.age < right.age) //如果左邊的小 就返回真 從小到大按照年齡進行排序
        {
            return true;
        }
        else
        {
            return false;
        }
    }
};

//仿函式的用法
void main93()
{
    set<Student,FuncStudent> set1;
    Student s1("s1", 31);
    Student s2("s2", 22);
    Student s3("s3", 17);
    Student s4("s4", 35);
    Student s5("s5", 31);
    pair<set<Student,FuncStudent>::iterator, bool> it1 = set1.insert(s1);
    if (it1.second == true)
    {
        cout << "插入s1成功" << endl;
    }
    else
    {
        cout << "插入s1失敗" << endl;
    }
    set1.insert(s2);
    /*set1.insert(s3);
    set1.insert(s4);*/

    pair<set<Student, FuncStudent>::iterator, bool> it5 = set1.insert(s5);
    if (it5.second == true)
    {
        cout << "插入s5成功" << endl;
    }
    else
    {
        cout << "插入s5失敗" << endl;
    }
    //如何知道插入的結果?
    // pair<iterator, bool> insert(const value_type& _Val)
    //如何判斷set1.insert函式的返回值


    //遍歷
    for (set<Student, FuncStudent>::iterator it = set1.begin(); it != set1.end(); it++)
    {
        cout << it->age << "\t" << it->name << endl;
    }
    cout << endl;
}
void main95()
{
    set<int> set1;
    for (int i = 0; i < 5; i++)
    {
        set1.insert(i + 1);
    }
    for (set<int>::iterator it = set1.begin(); it != set1.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
    set<int>::iterator it0 =set1.find(5);
    cout << "it0: " << *it0 << endl;

    int num = set1.count(5);//找值為5的個數
    cout << "mum: " << num << endl;
    
    set<int>::iterator it3 = set1.upper_bound(3);//大於3的元素迭代器位置
    cout << "大於3的迭代器位置 " << *it3 << endl;
    set<int>::iterator it4 = set1.lower_bound(3);//大於等於3的元素迭代器位置
    cout << "大於等於3的迭代器位置 " << *it4 << endl;

    pair<set<int>::iterator, set<int>::iterator> mypair = set1.equal_range(3);//找大於等於3和大於三的迭代器位置
    set<int>::iterator it5 = mypair.first;//3
    cout << "it5 " << *it5 << endl;
    set<int>::iterator it6 = mypair.second;//4
    cout << "it6 " << *it6 << endl;
}
int main()
{

    //main91();
    //main92();
    //main93();
    main95();
    system("pause");
    return 0;
}

multiset用法:

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


void main1001()
{
    multiset<int> set1;


    int temp = 0;
    printf("請輸入multiset集合的值:");
    scanf_s("%d", &temp);
    while (temp != 0)
    {
        set1.insert(temp);
        printf("請輸入multiset集合的值:");
        scanf_s("%d", &temp);
    }
    //遍歷
    for (multiset<int>::iterator it = set1.begin(); it != set1.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
    while (!set1.empty())
    {
        multiset<int>::iterator it = set1.begin();
        cout << *it << " ";
        set1.erase(it); 
    }


}

int main()
{

    main1001();
    system("pause");
    return 0;
}