目录
1 概述
集合(set)是按照特定顺序存储唯一元素的容器。
在集合中,元素的值也标识它(值本身就是键,类型为T),并且每个值都必须是唯一的。集合中元素的值不能在容器中修改(元素总是常量),但可以从容器中插入或删除它们。
在内部,集合中的元素总是按照其内部比较对象(类型为Compare)指示的特定严格弱排序标准进行排序。
集合容器通常比无序集合容器(unordered_set)通过关键字访问单个元素的速度慢,但它们允许根据子集的顺序直接迭代。
集合通常被实现为二叉搜索树
容器特性:
- 关联性 关联容器中的元素由它们的键(Key)引用,而不是由它们在容器中的绝对位置引用。
- 有序性 容器中的元素始终遵循严格的顺序。所有插入的元素都按此顺序给定一个位置。
- 集合 元素的值也是用来识别它的键(Key)。
- 唯一性 容器中没有两个元素可以具有等效的键。
- 分配器感知 容器使用分配器对象来动态处理其存储需求。
其类图如下:
2 使用实例
void SetSuite::find()
{
std::set<int> a = { 1, 2, 3, 4, 5 };
auto it = a.find(5);
TEST_ASSERT_EQUALS(5, *it)
it = a.find(6);
TEST_ASSERT_EQUALS(true, it == a.end())
}
3 接口使用
3.1 construct
bool function_compare(int l, int r) { return l < r; }
struct object_compare
{
bool operator()(const int& l, const int& r) { return l < r; }
};
void SetSuite::construct()
{
std::set<int> a;
int values [] = { 10, 20, 30, 40, 50, 50};
std::set<int> b(values, values + 5);
std::set<int> c(values, values + 6);
std::set<int> d(b);
std::set<int> e(b.begin(), b.end());
std::set<int, object_compare> f;
std::set<int, bool (*)(int, int)> g(function_compare);
std::set<int> h = { 1, 2, 3, 4, 5, 6 };
TEST_ASSERT_EQUALS(true, a.empty())
TEST_ASSERT_EQUALS(5, b.size())
TEST_ASSERT_EQUALS(5, c.size())//Unique vaue
TEST_ASSERT_EQUALS(5, d.size())
TEST_ASSERT_EQUALS(5, e.size())
TEST_ASSERT_EQUALS(true, f.empty())
TEST_ASSERT_EQUALS(true, g.empty())
TEST_ASSERT_EQUALS(6, h.size())
}
说明:
- 构造时可以指定函数对象作为比较函数
- 构造时可以指定函数指针作为比较函数
3.2 assigns
void SetSuite::assigns()
{
int values[] = { 5, 3, 2, 1, 8, 9 };
std::set<int> a(std::begin(values), std::end(values));
std::set<int> b;
std::set<int> c;
b = a;
c = { 5, 3, 2, 1, 8, 9 };
TEST_ASSERT_EQUALS(6, a.size())
a = std::set<int>();
TEST_ASSERT_EQUALS(0, a.size())
TEST_ASSERT_EQUALS(6, b.size())
TEST_ASSERT_EQUALS(6, c.size())
}
3.3 iterators
void SetSuite::iterators()
{
int values[] = { 5, 3, 2, 1, 8, 9 };
int array[] = { 1, 2, 3, 5, 8, 9 };
int rarray[] = { 9, 8, 5, 3, 2, 1 };
std::set<int> a(std::begin(values), std::end(values));
int index = 0;
for(auto it = a.begin(); it != a.end(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
index = 0;
for(auto it = a.cbegin(); it != a.cend(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
index = 0;
for(auto it = a.rbegin(); it != a.rend(); ++it)
TEST_ASSERT_EQUALS(rarray[index++], *it)
index = 0;
for(auto it = a.crbegin(); it != a.crend(); ++it)
TEST_ASSERT_EQUALS(rarray[index++], *it)
}
3.4 capacity
void SetSuite::capacity()
{
std::set<int> a;
std::set<int> b = { 1, 2, 3, 4, 5 };
TEST_ASSERT_EQUALS(true, a.empty())
TEST_ASSERT_EQUALS(0, a.size())
TEST_ASSERT_EQUALS(5, b.size())
TEST_ASSERT_EQUALS(b.max_size(), a.max_size())
}
3.5 insert
void SetSuite::insert()
{
std::set<int> a;
std::set<int> b;
std::set<int> c;
std::set<int>::iterator it;
for(int i = 1; i <= 5; i++) a.insert(i * 10); //10 20 30 40 50
std::pair<std::set<int>::iterator,bool> r = a.insert(20);//20 no inserted
if(r.second == false)
{
it = r.first;
TEST_ASSERT_EQUALS(20, *it)//*it = 20
}
a.insert(it, 27);//10 20 27 30 40 50
a.insert(it, 26);//10 20 26 27 30 40 50
a.insert(it, 28);//10 20 26 27 28 30 40 50
b.insert(a.begin(), a.end());
int array[] = { 10, 20, 26, 27, 28, 30, 40, 50};
c.insert({ 10, 20, 26, 27, 28, 30, 40, 50});
int index = 0;
for(auto it = a.begin(); it != a.end(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
index = 0;
for(auto it = b.begin(); it != b.end(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
index = 0;
for(auto it = c.begin(); it != c.end(); ++it)
TEST_ASSERT_EQUALS(array[index++], *it)
}
说明:
- 不带位置参数插入函数,返回std::pair对象,pair::first指新加入元素或集合中已存在元素,pair::second为true说明插入成功,为false说明集合中已有该元素
- 带位置参数插入函数,返回iterator,指向新加入元素或集合中已存在元素。
3.6 erase
void SetSuite::erase()
{
std::set<int> a = { 10, 20, 26, 27, 28, 30, 40, 50 };
auto it = a.erase(a.begin()); //20, 26, 27, 28, 30, 40, 50
TEST_ASSERT_EQUALS(20, *it)
TEST_ASSERT_EQUALS(1, a.erase(26)) //20, 27, 28, 30, 40, 50
TEST_ASSERT_EQUALS(0, a.erase(26)) //20, 27, 28, 30, 40, 50
it = a.begin();
++it;
TEST_ASSERT_EQUALS(27, *it)
it = a.erase(it, a.end()); //20
TEST_ASSERT_EQUALS(true, it == a.end())
TEST_ASSERT_EQUALS(1, a.size())
}
说明:
- 按值删除返回删除元素个数
- 按位置删除返回iterator指向被删除元素的下一位置
3.7 swap
void SetSuite::swap()
{
std::set<int> a = { 1, 2, 3, 4, 5 };
std::set<int> b;
TEST_ASSERT_EQUALS(5, a.size())
TEST_ASSERT_EQUALS(0, b.size())
a.swap(b);
TEST_ASSERT_EQUALS(0, a.size())
TEST_ASSERT_EQUALS(5, b.size())
}
3.8 clear
void SetSuite::clear()
{
std::set<int> a = { 1, 2, 3, 4, 5 };
TEST_ASSERT_EQUALS(5, a.size())
a.clear();
TEST_ASSERT_EQUALS(0, a.size())
}
3.9 emplace
void SetSuite::emplace()
{
std::set<std::string> names;
names.emplace("James");
names.emplace("Tom");
TEST_ASSERT_EQUALS(2, names.size())
auto it = names.emplace("James");
TEST_ASSERT_EQUALS(false, it.second)
TEST_ASSERT_EQUALS(2, names.size())
}
说明:
- 返回值为std::pair对象,pair::first指新加入元素或集合中已存在元素,pair::second为true说明插入成功,为false说明集合中已有该元素
3.1 emplace_hint
void SetSuite::emplace_hint()
{
std::set<std::string> names = { "James", "Tom"};
auto it = names.emplace_hint(names.begin(), "Rose");
TEST_ASSERT_EQUALS("Rose", *it)
it = names.emplace_hint(it, "Tom");
TEST_ASSERT_EQUALS("Tom", *it)
}
说明:
- 返回值为iterator对象,指向新加入元素或集合中已存在元素。
3.10 key_comp/value_comp
void SetSuite::key_comp()
{
int array [] = { 1, 2, 3, 4, 5 };
std::set<int> a(array, array + 5);
std::set<int> b;
std::set<int>::key_compare compare = a.key_comp();
for(int i : a)
{
if(compare(i ,5))
b.insert(i);
}
int index = 0;
for(int i : b)
{
TEST_ASSERT_EQUALS(array[index++], i)
}
TEST_ASSERT_EQUALS(4, b.size())
}
void SetSuite::value_comp()
{
int array [] = { 1, 2, 3, 4, 5 };
std::set<int> a(array, array + 5);
std::set<int> b;
std::set<int>::value_compare compare = a.value_comp();
for(int i : a)
{
if(compare(i ,5))
b.insert(i);
}
int index = 0;
for(int i : b)
{
TEST_ASSERT_EQUALS(array[index++], i)
}
TEST_ASSERT_EQUALS(4, b.size())
}
说明:
- 对set来说,key就是value,所以key_comp和value_comp是等效的
3.11 find/count
void SetSuite::find()
{
std::set<int> a = { 1, 2, 3, 4, 5 };
auto it = a.find(5);
TEST_ASSERT_EQUALS(5, *it)
it = a.find(6);
TEST_ASSERT_EQUALS(true, it == a.end())
}
void SetSuite::count()
{
std::set<int> a = { 1, 2, 3, 4, 5 };
TEST_ASSERT_EQUALS(1, a.count(5))
TEST_ASSERT_EQUALS(0, a.count(6))
}
3.12 lower_bound/upper_bound/equal_range
void SetSuite::lower_bound()
{
std::set<int> a = { 10, 20, 30, 40, 50 };
auto it = a.lower_bound(25);//>=25
TEST_ASSERT_EQUALS(30, *it)
it = a.lower_bound(40);//>=40
TEST_ASSERT_EQUALS(40, *it)
it = a.lower_bound(60);
TEST_ASSERT_EQUALS(true, it == a.end())
}
void SetSuite::upper_bound()
{
std::set<int> a = { 10, 20, 30, 40, 50 };
auto it = a.upper_bound(30); // > 30
TEST_ASSERT_EQUALS(40, *it)
it = a.upper_bound(60);// > 60
TEST_ASSERT_EQUALS(true, it == a.end())
}
void SetSuite::equal_range()
{
std::set<int> a = { 10, 20, 30, 40, 50 };
auto it = a.equal_range(30); // >=30 & > 30
TEST_ASSERT_EQUALS(30, *it.first)
TEST_ASSERT_EQUALS(40, *it.second )
it = a.equal_range(25); // >= 25 & > 25
TEST_ASSERT_EQUALS(30, *it.first)
TEST_ASSERT_EQUALS(30, *it.second)
}
说明:
- lower_bound 返回第一个大于等(>=)于指定值的iterator
- upper_bound 返回第一个大于(>)指定值的iterator
- equal_range 返回std::pair对象, pair::first是第一个大于等(>=)于指定值的iterator,pair::second是第一个大于(>)指定值的iterator
3.13 get_allocator
void SetSuite::get_allocator()
{
std::set<int> a;
auto allocator = a.get_allocator();
int *p = allocator.allocate(5);
TEST_ASSERT_EQUALS(true, p != nullptr)
for(int i = 1; i <= 5; i++)
p[i] = i * 10;
allocator.deallocate(p, 5);
try
{
p = allocator.allocate(allocator.max_size() + 1);
}
catch(...)
{
p = nullptr;
}
TEST_ASSERT_EQUALS(true, p == nullptr)
}