set集合容器

set集合容器實現了紅黑樹(Red-Black Tree)的平衡二叉件所屬的數據結構,在插入元素時,他會自動調整二叉樹的排列,把該元素放到適當的位置,以確保每個子樹根節點的鍵值大於左子樹所有節點的鍵值,而小於右子樹所有節點的鍵值;另外,還得確保根節點左子樹的高度與右子樹的高度相等,這樣,二叉樹的高度最小,從而檢索速度最快。要注意的是,它不會重複插入相同鍵值的元素,而採取忽略處理


平衡二叉檢索樹的檢索使用中序遍歷算法,檢索效率高於vectordeque、和list等容器。另外,採用中序遍歷算法可將鍵值由小到大遍歷出來,所以,可以理解爲平衡二叉檢索樹在插入元素時,就會自動將元素按鍵值由小到大的順序排列


對於set容器中的鍵值,不可直接去修改。因爲如果把容器中的一個鍵值修改了,set容器就會根據新的鍵值旋轉子樹,以保持新的平衡,這樣,修改的鍵值很可能就不在原先那個位置上了。換句話來說,構造set集合的主要目的就是爲了快速檢索


multiset(多重集合容器)、map(映照容器)和multimap(多重映照容器)的內部結構也是平衡二叉檢索樹。


使用set對象前,需要程序的頭文件中包含聲明“#include <set>”


1.1元素的插入與中序遍歷

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

int main(int argc, const char * argv[]) {
    
    //定義一個元素類型爲int的集合對象s,當前沒有任何元素
    set<int> s;
    
    //插入5個元素,但由於8被插入了兩次,第二次插入的8並沒有執行
    s.insert(8);  //第一次插入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.2 元素的反向遍歷

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

int main(int argc, const char * argv[]) {
    
    //定義一個元素類型爲int的集合對象s,當前沒有任何元素
    set<int> s;
    
    //插入5個元素,但由於8被插入了兩次,第二次插入的8並沒有執行
    s.insert(8);  //第一次插入8,可以插入
    s.insert(1);
    s.insert(12);
    s.insert(6);
    s.insert(8);  //第二次插入8,重複元素,不可以插入
    
    //反向遍歷集合中的元素

    set<int>::reverse_iterator rit;  //定義反向迭代器
    for (rit = s.rbegin(); rit != s.rend(); rit++) {
        cout << *rit << " ";
    }
    return 0;
}

1.3元素的刪除

刪除的對象可以是某個迭代器位置上的元素、等於某鍵值的元素、一個區間上的元素和清空集合。

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

int main(int argc, const char * argv[]) {
    
    //定義一個元素類型爲int的集合對象s,當前沒有任何元素
    set<int> s;
    
    //插入5個元素,但由於8被插入了兩次,第二次插入的8並沒有執行
    s.insert(8);  //第一次插入8,可以插入
    s.insert(1);
    s.insert(12);
    s.insert(6);
    s.insert(8);  //第二次插入8,重複元素,不可以插入
    
    //刪除鍵值爲6的那個元素
    s.erase(6);
    
    //中序遍歷集合中的元素
    //定義前向迭代器
    set<int>::iterator it;
    for (it = s.begin(); it != s.end(); it++) {
        cout << *it << " ";
    }
    return 0;
}

1.4元素的檢索

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

int main(int argc, const char * argv[]) {
    
    //定義一個元素類型爲int的集合對象s,當前沒有任何元素
    set<int> s;
    
    //插入5個元素,但由於8被插入了兩次,第二次插入的8並沒有執行
    s.insert(8);  //第一次插入8,可以插入
    s.insert(1);
    s.insert(12);
    s.insert(6);
    s.insert(8);  //第二次插入8,重複元素,不可以插入
    
    //定義前向迭代器
    set<int>::iterator it;
    
    //查找鍵值爲6的元素
    it = s.find(6);
    
    if (it != s.end()) {
        cout << *it << endl;
    } else {//沒找到
        cout << "not find it" << endl;
    }
    
    
    it = s.find(20);
    if (it != s.end()) {
        cout << *it << endl;
    } else {
        cout << "沒有找到" << endl;
    }
    return 0;
}

1.5自定義比較函數

(1)如果元素不是結構體,那麼,可以編寫比較函數。

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

//自定義比較函數,Compare,重載"()"操作符
struct Compare
{   
    bool operator() (const int &a, const int &b)
    {
        if (a != b)
            return a > b;
        else
            return a > b;
    }

};
int main(int argc, const char * argv[]) {
    
    //定義一個元素類型爲int的集合對象s,當前沒有任何元素
    set<int, Compare> s;
    
    //插入5個元素,但由於8被插入了兩次,第二次插入的8並沒有執行
    s.insert(8);  //第一次插入8,可以插入
    s.insert(1);
    s.insert(12);
    s.insert(6);
    s.insert(8);  //第二次插入8,重複元素,不可以插入
    
    //定義前向迭代器
    set<int, Compare>::iterator it;
    for (it = s.begin(); it != s.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;
    
    //清空元素
    s.clear();
    cout << s.size() << endl;
    return 0;
}

(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(int argc, const char * argv[]) {
    
    //定義元素類型爲Info結構體的集合對象s,當前沒有任何元素
    set<Info> s;
    
    Info info;
    //插入三個元素
    info.name = "Kevin";
    info.score = 90;
    s.insert(info);
    
    info.name = "Yuki";
    info.score = 80;
    s.insert(info);
    
    info.name = "Tony";
    info.score = 85;
    s.insert(info);
    
    set<Info>::iterator it;  //定義前向迭代器
    for (it = s.begin(); it != s.end(); it++) {
        cout << (*it).name << " : " << (*it).score << endl;
    }
    cout << endl;
    return 0;
}


發佈了78 篇原創文章 · 獲贊 12 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章