C++/C++11中std::set用法汇总
一個容器就是一些特定類型對象的集合。順序容器(sequential container)為程序員提供了控制元素存儲和訪問順序的能力。這種順序不依賴于元素的值,而是與元素加入容器時的位置相對應。與之相對的,有序和無序關聯容器,則根據關鍵字的值來存儲元素。
標準庫還提供了三種容器適配器,分別為容器操作定義了不同的接口,來與容器類型適配:stack、queue和priority_queue。適配器(adaptor)是標準庫中的一個通用概念。容器、迭代器和函數都有適配器。本質上,一個適配器是一種機制,能使某種事物的行為看起來像另外一種事物一樣。一個容器適配器接受一種已有的容器類型,使其行為看起來像一種不同的類型。
順序容器包括vector、deque、list、forward_list、array、string,所有順序容器都提供了快速順序訪問元素的能力。
關聯容器和順序容器有著根本的不同:關聯容器中的元素是按關鍵字來保存和訪問的。與之相對,順序容器中的元素是按它們在容器中的位置來順序保存和訪問的。
類似順序容器,關聯容器也是模板。
關聯容器不支持順序容器的位置相關的操作。原因是關聯容器中元素是根據關鍵字存儲的,這些操作對關聯容器沒有意義。而且,關聯容器也不支持構造函數或插入操作這些接受一個元素值和一個數量值得操作。
關聯容器支持高效的關鍵字查找和訪問。兩個主要的關聯容器(associative container)類型是map和set。map中的元素是一些關鍵字----值(key--value)對:關鍵字起到索引的作用,值則表示與索引相關聯的數據。set中每個元素只包含一個關鍵字:set支持高效的關鍵字查詢操作----檢查一個給定關鍵字是否在set中。
標準庫提供8個關聯容器:
(1)、按關鍵字有序保存元素:map(關聯數組:保存關鍵字----值對);set(關鍵字即值,即只保存關鍵字的容器);multimap(關鍵字可重復出現的map);multiset(關鍵字可重復出現的set);
(2)、無序集合:unordered_map(用哈希函數組織的map);unordered_set(用哈希函數組織的set);unordered_multimap(哈希組織的map,關鍵字可以重復出現);unordered_multiset(哈希組織的sest,關鍵字可以重復出現)。
map是關鍵字----值對的集合,與之相對,set就是關鍵字的簡單集合。當只是想知道一個值是否存在時,set是最有用的。
在set中每個元素的值都唯一,而且系統能根據元素的值自動進行排序。Set中元素的值不能直接被改變。set內部采用的是一種非常高效的平衡檢索二叉樹:紅黑樹,也稱為RB樹(Red-Black Tree)。RB樹的統計性能要好于一般平衡二叉樹。
下面是從cplusplus和cppreference網站摘錄的測試代碼:
#include "set.hpp"
#include <set>
#include <iostream>
#include <string>
#include <cassert>
#include <chrono>
#include <functional>
#include <iomanip>// reference: http://www.cplusplus.com/reference/set/set/
static bool fncomp(int lhs, int rhs) { return lhs<rhs; }struct classcomp {bool operator() (const int& lhs, const int& rhs) const{return lhs<rhs;}
};int test_set_cplusplus()
{
{ // set:構造函數std::set<int> first; // empty set of intsint myints[] = { 10, 20, 30, 40, 50 };std::set<int> second(myints, myints + 5); // rangestd::set<int> third(second); // a copy of secondstd::set<int> fourth(second.begin(), second.end()); // iterator ctor.std::set<int, classcomp> fifth; // class as Comparebool(*fn_pt)(int, int) = fncomp;std::set<int, bool(*)(int, int)> sixth(fn_pt); // function pointer as Compare
}{ // begin/end:返回指向第一個元素的迭代/返回指向最后一個元素之后的迭代器,不是最后一個元素int myints[] = { 75, 23, 65, 42, 13 };std::set<int> myset(myints, myints + 5);std::cout << "myset contains:";for (std::set<int>::iterator it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';
}{ // clear:清除所有元素std::set<int> myset;myset.insert(100);myset.insert(200);myset.insert(300);std::cout << "myset contains:";for (std::set<int>::iterator it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';myset.clear();myset.insert(1101);myset.insert(2202);std::cout << "myset contains:";for (std::set<int>::iterator it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';
}{ // count:判斷某一個關鍵字是否在set內,返回0或者1std::set<int> myset;// set some initial values:for (int i = 1; i<5; ++i) myset.insert(i * 3); // set: 3 6 9 12for (int i = 0; i < 10; ++i) {std::cout << i;if (myset.count(i) != 0)std::cout << " is an element of myset.\n";elsestd::cout << " is not an element of myset.\n";}}{ // cbegin/cend(c++11): Returns a const_iterator pointing to the first element in the container/// Returns a const_iterator pointing to the past-the-end element in the containerstd::set<int> myset = { 50, 20, 60, 10, 25 };std::cout << "myset contains:";for (auto it = myset.cbegin(); it != myset.cend(); ++it)std::cout << ' ' << *it;std::cout << '\n';
}{ // crbegin/crend(c++11):Return const_reverse_iterator to reverse beginning/// Return const_reverse_iterator to reverse endstd::set<int> myset = { 50, 20, 60, 10, 25 };std::cout << "myset backwards:";for (auto rit = myset.crbegin(); rit != myset.crend(); ++rit)std::cout << ' ' << *rit;std::cout << '\n';
}{ // emplace(c++11):如果新元素的值是唯一的,將插入該元素std::set<std::string> myset;myset.emplace("foo");myset.emplace("bar");auto ret = myset.emplace("foo");if (!ret.second) std::cout << "foo already exists in myset\n";
}{ // emplace_hint(c++11):Construct and insert element with hintstd::set<std::string> myset;auto it = myset.cbegin();myset.emplace_hint(it, "alpha");it = myset.emplace_hint(myset.cend(), "omega");it = myset.emplace_hint(it, "epsilon");it = myset.emplace_hint(it, "beta");std::cout << "myset contains:";for (const std::string& x : myset)std::cout << ' ' << x;std::cout << '\n';
}{ // empty:如果集合為空,返回truestd::set<int> myset;myset.insert(20);myset.insert(30);myset.insert(10);std::cout << "myset contains:";while (!myset.empty()) {std::cout << ' ' << *myset.begin();myset.erase(myset.begin());}std::cout << '\n';
}{ // equal_range:返回集合中與給定值相等的上下限的兩個迭代器std::set<int> myset;for (int i = 1; i <= 5; i++) myset.insert(i * 10); // myset: 10 20 30 40 50std::pair<std::set<int>::const_iterator, std::set<int>::const_iterator> ret;ret = myset.equal_range(30);std::cout << "the lower bound points to: " << *ret.first << '\n';std::cout << "the upper bound points to: " << *ret.second << '\n';
}{ // erase:刪除集合中的元素std::set<int> myset;std::set<int>::iterator it;// insert some values:for (int i = 1; i<10; i++) myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90it = myset.begin();++it; // "it" points now to 20myset.erase(it);myset.erase(40);it = myset.find(60);myset.erase(it, myset.end());std::cout << "myset contains:";for (it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';
}{ // find:返回一個指向被查找到元素的迭代器,如果沒找到則返回end()std::set<int> myset;std::set<int>::iterator it;// set some initial values:for (int i = 1; i <= 5; i++) myset.insert(i * 10); // set: 10 20 30 40 50it = myset.find(20);myset.erase(it);myset.erase(myset.find(40));std::cout << "myset contains:";for (it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';
}{ // get_allocator:返回集合set的分配器std::set<int> myset;int * p;unsigned int i;// allocate an array of 5 elements using myset's allocator:p = myset.get_allocator().allocate(5);// assign some values to arrayfor (i = 0; i<5; i++) p[i] = (i + 1) * 10;std::cout << "The allocated array contains:";for (i = 0; i<5; i++) std::cout << ' ' << p[i];std::cout << '\n';myset.get_allocator().deallocate(p, 5);
}{ // insert:在集合中插入元素std::set<int> myset;std::set<int>::iterator it;std::pair<std::set<int>::iterator, bool> ret;// set some initial values:for (int i = 1; i <= 5; ++i) myset.insert(i * 10); // set: 10 20 30 40 50ret = myset.insert(20); // no new element insertedif (ret.second == false) it = ret.first; // "it" now points to element 20myset.insert(it, 25); // max efficiency insertingmyset.insert(it, 24); // max efficiency insertingmyset.insert(it, 26); // no max efficiency insertingint myints[] = { 5, 10, 15 }; // 10 already in set, not insertedmyset.insert(myints, myints + 3);std::cout << "myset contains:";for (it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';
}{ // key_comp:Returns a copy of the comparison object used by the containerstd::set<int> myset;int highest;std::set<int>::key_compare mycomp = myset.key_comp();for (int i = 0; i <= 5; i++) myset.insert(i);std::cout << "myset contains:";highest = *myset.rbegin();std::set<int>::iterator it = myset.begin();do {std::cout << ' ' << *it;} while (mycomp(*(++it), highest));std::cout << '\n';
}{ // lower_bond:返回指向大于(或等于)某值的第一個元素的迭代器std::set<int> myset;std::set<int>::iterator itlow, itup;for (int i = 1; i<10; i++) myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90itlow = myset.lower_bound(30); // ^itup = myset.upper_bound(60); // ^myset.erase(itlow, itup); // 10 20 70 80 90std::cout << "myset contains:";for (std::set<int>::iterator it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';
}{ // max_size:返回集合能容納的元素的最大限值int i;std::set<int> myset;if (myset.max_size() > 1000) {for (i = 0; i<1000; i++) myset.insert(i);std::cout << "The set contains 1000 elements.\n";} elsestd::cout << "The set could not hold 1000 elements.\n";
}{ // operator =:Assigns new contents to the container, replacing its current contentint myints[] = { 12, 82, 37, 64, 15 };std::set<int> first(myints, myints + 5); // set with 5 intsstd::set<int> second; // empty setsecond = first; // now second contains the 5 intsfirst = std::set<int>(); // and first is emptystd::cout << "Size of first: " << int(first.size()) << '\n';std::cout << "Size of second: " << int(second.size()) << '\n';
}{ // rbegin/rend:返回指向集合中最后一個元素的反向迭代器/返回指向集合中第一個元素的反向迭代器int myints[] = { 21, 64, 17, 78, 49 };std::set<int> myset(myints, myints + 5);std::set<int>::reverse_iterator rit;std::cout << "myset contains:";for (rit = myset.rbegin(); rit != myset.rend(); ++rit)std::cout << ' ' << *rit;std::cout << '\n';
}{ // size:集合中元素的數目std::set<int> myints;std::cout << "0. size: " << myints.size() << '\n';for (int i = 0; i<10; ++i) myints.insert(i);std::cout << "1. size: " << myints.size() << '\n';myints.insert(100);std::cout << "2. size: " << myints.size() << '\n';myints.erase(5);std::cout << "3. size: " << myints.size() << '\n';
}{ // swap:交換兩個集合變量int myints[] = { 12, 75, 10, 32, 20, 25 };std::set<int> first(myints, myints + 3); // 10,12,75std::set<int> second(myints + 3, myints + 6); // 20,25,32first.swap(second);std::cout << "first contains:";for (std::set<int>::iterator it = first.begin(); it != first.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';std::cout << "second contains:";for (std::set<int>::iterator it = second.begin(); it != second.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';
}{ // upper_bound:返回大于某個值元素的迭代器std::set<int> myset;std::set<int>::iterator itlow, itup;for (int i = 1; i<10; i++) myset.insert(i * 10); // 10 20 30 40 50 60 70 80 90itlow = myset.lower_bound(30); // ^itup = myset.upper_bound(60); // ^myset.erase(itlow, itup); // 10 20 70 80 90std::cout << "myset contains:";for (std::set<int>::iterator it = myset.begin(); it != myset.end(); ++it)std::cout << ' ' << *it;std::cout << '\n';
}{ // value_comp:Returns a copy of the comparison object used by the containerstd::set<int> myset;std::set<int>::value_compare mycomp = myset.value_comp();for (int i = 0; i <= 5; i++) myset.insert(i);std::cout << "myset contains:";int highest = *myset.rbegin();std::set<int>::iterator it = myset.begin();do {std::cout << ' ' << *it;} while (mycomp(*(++it), highest));std::cout << '\n';
}{ // relational operators:==/!=/</<=/>/>=std::set<int> foo, bar;foo.insert(10);bar.insert(20);bar.insert(30);foo.insert(40);// foo ({10,40}) vs bar ({20,30}):if (foo == bar) std::cout << "foo and bar are equal\n";if (foo != bar) std::cout << "foo and bar are not equal\n";if (foo< bar) std::cout << "foo is less than bar\n";if (foo> bar) std::cout << "foo is greater than bar\n";if (foo <= bar) std::cout << "foo is less than or equal to bar\n";if (foo >= bar) std::cout << "foo is greater than or equal to bar\n";
}return 0;
}// reference: http://en.cppreference.com/w/cpp/container/set
struct Point { double x, y; };
struct PointCmp {bool operator()(const Point& lhs, const Point& rhs) const {return std::hypot(lhs.x, lhs.y) < std::hypot(rhs.x, rhs.y);}
};static void display_sizes(const std::set<int> &nums1, const std::set<int> &nums2, const std::set<int> &nums3)
{std::cout << "nums1: " << nums1.size()<< " nums2: " << nums2.size()<< " nums3: " << nums3.size() << '\n';
}class Dew
{
private:int a;int b;int c;public:Dew(int _a, int _b, int _c): a(_a), b(_b), c(_c){}bool operator<(const Dew &other) const{if (a < other.a)return true;if (a == other.a && b < other.b)return true;return (a == other.a && b == other.b && c < other.c);}
};const int nof_operations = 120;int set_emplace() {std::set<Dew> set;for (int i = 0; i < nof_operations; ++i)for (int j = 0; j < nof_operations; ++j)for (int k = 0; k < nof_operations; ++k)set.emplace(i, j, k);return set.size();
}int set_insert() {std::set<Dew> set;for (int i = 0; i < nof_operations; ++i)for (int j = 0; j < nof_operations; ++j)for (int k = 0; k < nof_operations; ++k)set.insert(Dew(i, j, k));return set.size();
}void timeit(std::function<int()> set_test, std::string what = "") {auto start = std::chrono::system_clock::now();int setsize = set_test();auto stop = std::chrono::system_clock::now();std::chrono::duration<double, std::milli> time = stop - start;if (what.size() > 0 && setsize > 0) {std::cout << std::fixed << std::setprecision(2)<< time.count() << " ms for " << what << '\n';}
}int test_set_cppreference()
{
{ // constructor: constructs the set // (1) Default constructorstd::set<std::string> a;a.insert("cat");a.insert("dog");a.insert("horse");for (auto& str : a) std::cout << str << ' ';std::cout << '\n';// (2) Iterator constructorstd::set<std::string> b(a.find("dog"), a.end());for (auto& str : b) std::cout << str << ' ';std::cout << '\n';// (3) Copy constructorstd::set<std::string> c(a);c.insert("another horse");for (auto& str : c) std::cout << str << ' ';std::cout << '\n';// (4) Move constructorstd::set<std::string> d(std::move(a));for (auto& str : d) std::cout << str << ' ';std::cout << '\n';std::cout << "moved-from set is ";for (auto& str : a) std::cout << str << ' ';std::cout << '\n';// (5) Initializer list constructorstd::set<std::string> e{ "one", "two", "three", "five", "eight" };for (auto& str : e) std::cout << str << ' ';std::cout << '\n';// custom comparisonstd::set<Point, PointCmp> z = { { 2, 5 }, { 3, 4 }, { 1, 1 } };z.insert({ 1, -1 }); // this fails because the magnitude of 1,-1 equals 1,1for (auto& p : z) std::cout << '(' << p.x << ',' << p.y << ") ";std::cout << '\n';
}{ // operator = : assigns values to the container std::set<int> nums1{ 3, 1, 4, 6, 5, 9 };std::set<int> nums2;std::set<int> nums3;std::cout << "Initially:\n";display_sizes(nums1, nums2, nums3);// copy assignment copies data from nums1 to nums2nums2 = nums1;std::cout << "After assigment:\n";display_sizes(nums1, nums2, nums3);// move assignment moves data from nums1 to nums3,// modifying both nums1 and nums3nums3 = std::move(nums1);std::cout << "After move assigment:\n";display_sizes(nums1, nums2, nums3);
}{ // get_allocator: returns the associated allocator
}{ // begin/end(cbegin/cend): returns an iterator to the beginning /returns an iterator to the endstd::set<int> set = { 6, 1, 3, 4, 2, 5 };for (auto it = set.begin(); it != set.end(); ++it)std::cout << *it << "\n";
}{ // rbegin/rend(crbegin/crend): returns a reverse iterator to the beginning /returns a reverse iterator to the end
}{ // empty: checks whether the container is empty std::set<int> numbers;std::cout << "Initially, numbers.empty(): " << numbers.empty() << '\n';numbers.insert(42);numbers.insert(13317);std::cout << "After adding elements, numbers.empty(): " << numbers.empty() << '\n';
}{ // size: returns the number of elements std::set<int> nums{ 1, 3, 5, 7 };std::cout << "nums contains " << nums.size() << " elements.\n";
}{ // max_size: returns the maximum possible number of elements std::set<char> s;std::cout << "Maximum size of a 'set' is " << s.max_size() << "\n";
}{ // clear: clears the contents
}{ // insert: inserts elementsstd::set<int> set;auto result_1 = set.insert(3);assert(result_1.first != set.end()); // it's a valid iteratorassert(*result_1.first == 3);if (result_1.second)std::cout << "insert done\n";auto result_2 = set.insert(3);assert(result_2.first == result_1.first); // same iteratorassert(*result_2.first == 3);if (!result_2.second)std::cout << "no insertion\n";
}{ // emplace(c++11): constructs element in-place set_insert();timeit(set_insert, "insert");timeit(set_emplace, "emplace");timeit(set_insert, "insert");timeit(set_emplace, "emplace");
}{ // emplace_hint(c++11): constructs elements in-place using a hint // reference: http://en.cppreference.com/w/cpp/container/set/emplace_hint
}{ // erase: erases elements std::set<int> c = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };// erase all odd numbers from cfor (auto it = c.begin(); it != c.end();)if (*it % 2 == 1)it = c.erase(it);else++it;for (int n : c)std::cout << n << ' ';
}{ // swap: swaps the contents
}{ // count: returns the number of elements matching specific key
}{ // find: finds element with specific key std::set<int> example = { 1, 2, 3, 4 };auto search = example.find(2);if (search != example.end()) {std::cout << "Found " << (*search) << '\n';}else {std::cout << "Not found\n";}
}{ // equal_range: returns range of elements matching a specific key
}{ // lower_bound: returns an iterator to the first element not less than the given key
}{ // upper_bound: returns an iterator to the first element greater than the given key
}{ // key_comp: returns the function that compares keys
}{ // value_comp: returns the function that compares keys in objects of type value_type
}return 0;
}
GitHub: https://github.com/fengbingchun/Messy_Test
總結
以上是生活随笔為你收集整理的C++/C++11中std::set用法汇总的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Caffe源码中Net文件分析
- 下一篇: C++中nothrow的介绍及使用