c++的 set 和 multiset 容器
阿新 • • 發佈:2020-10-14
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; }