标签:
使用
set
和multiset
前包含头文件<set>
set
、multiset
都是集合类,差别在与set
中不允许有重复元素,multiset
中允许有重复元素。他们都是有序集合。
std::set is an associative container(关联容器) that contains a sorted set of unique objects of type Key. Sorting is done using the key comparison function Compare. Search, removal, and insertion operations have logarithmic complexity. Sets are usually implemented as red-black trees.
构造函数有如下这多:
下面的举例是常用的构造方式,从下面的代码中我们很容易掌握常用的构造方法。
#include "stdafx.h"
#include <iostream>
#include <string>
#include <set>
// Helper function for printing pairs.
template<class Ch, class Tr, class A, class B> inline
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& stream, std::pair<A, B> p)
{
return stream << ‘(‘ << p.first << ", " << p.second << ‘)‘;
}
// Helper function for printing containers.
template<class Ch, class Tr, class Co>
std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& stream, Co& c)
{
stream << ‘{‘ << *c.begin();
for (auto it = ++(c.begin()); it != c.end(); ++it)
stream << ", " << *it;
stream << ‘}‘ << std::endl;
return stream;
}
int main()
{
// (1) Default constructor
std::set<std::string> a; //empty set
a.insert("something");
a.insert("anything");
a.insert("that thing");
std::cout << "a = " << a; // sorted
// (2) Iterator constructor
std::set<std::string> b(a.find("anything"), a.end()); // find() return iterator
std::cout << std::string(80, ‘-‘) << std::endl;
std::cout << "b = " << b; // a == b
// (3) Copy constructor
std::set<std::string> c(a);
c.insert("another thing"); // insert and sorted
std::cout << std::string(80, ‘-‘) << std::endl;
std::cout << "a = " << a;
std::cout << "c = " << c;
// (4) Move constructor
std::set<std::string> d(std::move(a)); // ok.ok.ok --- a to be empty
std::cout << std::string(80, ‘-‘) << std::endl;
std::cout << "a = nullptr" << std::endl;
std::cout << "d = " << d;
// (5) Initializer list constructor
std::set<std::string> e{
"one", "two", "three", "five", "eight"
};
std::cout << std::string(80, ‘-‘) << std::endl;
std::cout << "e = " << e;
}
输出:
a = {anything, something, that thing}
--------------------------------------------------------------------------------
b = {anything, something, that thing}
--------------------------------------------------------------------------------
a = {anything, something, that thing}
c = {another thing, anything, something, that thing}
--------------------------------------------------------------------------------
a = nullptr
d = {anything, something, that thing}
--------------------------------------------------------------------------------
e = {eight, five, one, three, two}
~set();
Destructs the container. The destructors of the elements are called and the used storage is deallocated. Note, that if the elements are pointers, the pointed-to objects are not destroyed.
析构函数会完成两个任务:1)调用set
中每个元素的析构函数,2)释放元素占用的空间
如果存储的元素值指针,那么指针指向的对象并不会释放,容易造成内存泄露。
示例代码如下:
#include <set>
#include <iostream>
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‘;
}
int main()
{
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 nums2
nums2 = nums1;
std::cout << "After assigment:\n";
display_sizes(nums1, nums2, nums3);
// move assignment moves data from nums1 to nums3,
// modifying both nums1 and nums3
nums3 = std::move(nums1); // move 将nums1对内存的所有权剥夺,通过调用上述的(2)赋值方式将内存所有权转交给nums3
std::cout << "After move assigment:\n";
display_sizes(nums1, nums2, nums3);
}
输出:
Initially:
nums1: 6 nums2: 0 nums3: 0
After assigment:
nums1: 6 nums2: 6 nums3: 0
After move assigment:
nums1: 0 nums2: 6 nums3: 6
allocator_type get_allocator() const;
Returns the allocator associated with the container.
c
表示 const
iterator begin();
const_iterator begin() const;
const_iterator cbegin() const; (since C++11)
iterator end();
const_iterator end() const;
const_iterator cend() const; (since C++11)
r
表示 reverse
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
const_reverse_iterator crbegin() const; (since C++11)
Returns a reverse iterator to the first element of the reversed container. It corresponds to the last element of the non-reversed container.
reverse_iterator rend();
const_reverse_iterator rend() const;
const_reverse_iterator crend() const; (since C++11)
bool empty() const;
Checks if the container has no elements, i.e. whether begin() == end().
size_type size() const;
Returns the number of elements in the container, i.e. std::distance(begin(), end()).
size_type max_size() const;
Returns the maximum number of elements the container is able to hold due to system or library implementation limitations,
返回的是当前容器在内存中所能分配的最大元素值-通常是一个较大的值,max_size() - size()
表示还能分配的元素个数。跟内存重新分配没有关系,只与系统和库实现相关。
#include <iostream>
#include <set>
int main()
{
std::set<char> s;
std::cout << "Maximum size of a ‘set‘ is " << s.max_size() << "\n";
}
输出:
Maximum size of a ‘set‘ is 18446744073709551615
void clear();
Removes all elements from the container.
说明:
1-2) 插入一个值,返回的是pair
, pair->first
指向插入值的迭代器, pair->second
返回是否插入成功,在下面的例子中很清楚。
3-4) 在指定位置插入指定值。
5)插入一个范围内的元素。
6)插入一个初始化列表,没什么意思。
#include <set>
#include <cassert>
#include <iostream>
int main()
{
std::set<int> set;
auto result_1 = set.insert(3);
// 返回的迭代器指向新插入的元素
assert(result_1.first != set.end()); // it‘s a valid iterator
assert(*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 iterator
assert(*result_2.first == 3);
if (!result_2.second) // 没有插入成功, 返回false
std::cout << "no insertion\n";
}
输出:
insert done
no insertion
template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args ); (since C++11)
Inserts a new element into the container by constructing it in-place with the given args if there is no element with the key in the container.
Careful use of emplace allows the new element to be constructed while avoiding unnecessary copy or move operations
#include <set>
#include <chrono>
#include <iostream>
#include <iomanip>
#include <functional>
const int nof_operations = 100500;
int set_emplace() {
std::set<int> set;
for(int i = 0; i < nof_operations; ++i) {
set.emplace(i);
}
return set.size();
}
int set_emplace_hint() {
std::set<int> set;
auto it = set.begin();
for(int i = 0; i < nof_operations; ++i) {
set.emplace_hint(it, i);
it = set.end();
}
return set.size();
}
int set_emplace_hint_wrong() {
std::set<int> set;
auto it = set.begin();
for(int i = nof_operations; i > 0; --i) {
set.emplace_hint(it, i);
it = set.end();
}
return set.size();
}
int set_emplace_hint_corrected() {
std::set<int> set;
auto it = set.begin();
for(int i = nof_operations; i > 0; --i) {
set.emplace_hint(it, i);
it = set.begin();
}
return set.size();
}
int set_emplace_hint_closest() {
std::set<int> set;
auto it = set.begin();
for(int i = 0; i < nof_operations; ++i) {
it = set.emplace_hint(it, i);
}
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 main() {
timeit(set_emplace); // stack warmup
timeit(set_emplace, "plain emplace");
timeit(set_emplace_hint, "emplace with correct hint");
timeit(set_emplace_hint_wrong, "emplace with wrong hint");
timeit(set_emplace_hint_corrected, "corrected emplace");
timeit(set_emplace_hint_closest, "emplace using returned iterator");
}
输出:
18.96 ms for plain emplace
7.95 ms for emplace with correct hint
19.39 ms for emplace with wrong hint
8.39 ms for corrected emplace
7.90 ms for emplace using returned iterator
1) 移除指定位置的元素,返回的迭代器指向后一个元素
2)移除指定范围的元素
3)移除指定值
void swap( set& other );
Exchanges the contents of the container with those of other. Does not invoke any move, copy, or swap operations on individual elements. All iterators and references remain valid
size_type count( const Key& key ) const; (1)
template< class K >
size_type count( const K& x ) const; (2) (since C++14)
1) 返回指定元素值的个数,只可能返回0或者1.因为不允许重复元素的存在.
2) Returns the number of elements with key that compares equivalent to the value x. This overload only participates in overload resolution if the qualified-id Compare::is_transparent is valid and denotes a type. They allow calling this function without constructing an instance of Key.
返回指向指定元素的迭代器,如果没有找到指定元素,那么返回尾后迭代器。将返回的迭代器和end()
比较是否相等可以判断是否找到指定元素。
#include <iostream>
#include <set>
int main()
{
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";
}
}
输出:
Found 2
std::pair<iterator,iterator> equal_range( const Key& key );
template< class K >
std::pair<iterator,iterator> equal_range( const K& x );
因为在集合中相等的元素连续存储,因此可以使用一个范围表示等于指定值的范围。
第一个迭代器指向不小于指定值的位置,第二个迭代器指向第一个大于指定值的位置。也就是[first,second)
。这两个迭代器也是lower_bound
和upper_bound
返回的迭代器指向的位置。
iterator lower_bound( const Key& key ); (1)
const_iterator lower_bound( const Key& key ) const; (1)
template< class K >
iterator lower_bound(const K& x); (2) (since C++14)
template< class K >
const_iterator lower_bound(const K& x) const; (2) (since C++14)
返回的迭代器指向不小于指定值的元素。
iterator upper_bound( const Key& key ); (1)
const_iterator upper_bound( const Key& key ) const; (1)
template< class K >
iterator upper_bound( const K& x ); (2) (since C++14)
template< class K >
const_iterator upper_bound( const K& x ) const; (2) (since C++14)
返回的迭代器指向第一个大于指定值的元素。
key_compare key_comp() const;
Returns the function object that compares the keys, which is a copy of this container’s
constructor argument comp. It is the same as value_comp.
std::set::value_compare value_comp() const;
Returns the function object that compares the values. It is the same as key_comp.
operator==,!=,<,<=,>,>=(std::set)
两个容器大小相同并且相同位置的值对应相等,那么返回true
。
template< class Key, class Compare, class Alloc >
void swap( set<Key,Compare,Alloc>& lhs, set<Key,Compare,Alloc>& rhs );
Specializes the std::swap algorithm for std::set. Swaps the contents of lhs and rhs. Calls lhs.swap(rhs).
标签:
原文地址:http://blog.csdn.net/yapian8/article/details/45064061