C++ set:无序世界中的有序指挥官

  在现实世界中,许多数据和元素都没有天然的顺序,比如人群、车辆或是数字的集合。我们常常需要一种方法,来将这些本来无序的事物整理成有序的结构,方便我们管理和访问。在 C++ 中,set就是这样一个“有序指挥官”,它能够在无序的世界中,快速为我们建立秩序,确保元素的有序性和高效的操作。

1.set简介

C++ 中的 set 是一种 关联容器,它存储唯一的元素,并保证这些元素按照一定的顺序排列。元素的顺序通常是 升序,但也可以根据自定义的比较函数来进行排序。与 vectorlist 等容器不同,set 不允许重复的元素,它会自动忽略重复插入的元素。

简而言之,set 是一个自动为我们整理无序数据的工具,它确保数据总是按顺序存储,并且不包含重复项。

1.1 序列式容器和关联性容器

我们已经接触过STL中的部分容器如:string、vector、list、deque、array、forward_list等,这
些容器统称为序列式容器,因为逻辑结构为线性序列的数据结构,两个位置存储的值之间⼀般没有紧密的关联关系,⽐如交换⼀下,他依旧是序列式容器。顺序容器中的元素是按他们在容器中的存储位置来顺序保存和访问的。
关联式容器也是⽤来存储数据的,与序列式容器不同的是,关联式容器逻辑结构通常是非线性结构, 两个位置有紧密的关联关系,交换⼀下,他的存储结构就被破坏了。顺序容器中的元素是按关键字来保存和访问的。关联式容器有map/set系列和unordered_map/unordered_set系列。

1.2 底层实现:红黑树的指挥棒

set 的有序性和高效性来自于其底层实现——红黑树。红黑树是一种自平衡的二叉查找树,它通过一些规则来保持树的平衡,确保树的高度始终在对数级别,从而保证了查找、插入和删除操作的高效性。

红黑树遵循以下五条规则:

  1. 节点的颜色:每个节点要么是红色,要么是黑色。
  2. 根节点是黑色:树的根节点总是黑色的。
  3. 红色节点的子节点是黑色:如果一个节点是红色的,那么它的子节点必须是黑色的。这意味着红色节点不能连续出现。
  4. 从任何节点到其所有叶子的简单路径包含相同数目的黑色节点:每条路径上黑色节点的数量必须相同。
  5. 所有叶子节点是黑色:红黑树的叶子节点(即空节点)是黑色的。

通过这五条规则,红黑树在任何插入和删除操作之后都能够重新平衡自己,保持树的高度不超过 2 * log(n),确保 O(log n) 的查找、插入和删除时间复杂度。

红黑树拥有以下特性,使得它成为了 C++ set 的理想选择:

  • 自平衡:插入和删除操作会自动调整树的结构,确保树的高度保持在 O(log n) 范围内。
  • 有序存储:树中的节点按顺序排列,这保证了元素的快速查找和排序。
  • O(log n) 时间复杂度:无论是查找、插入还是删除操作,时间复杂度都是 O(log n),即使在数据量极大的情况下也能保持高效。

2. set的构造函数

empty (1)
explicit set (const key_compare& comp = key_compare(),
              const allocator_type& alloc = allocator_type());
range (2)
template <class InputIterator>
  set (InputIterator first, InputIterator last,
       const key_compare& comp = key_compare(),
       const allocator_type& alloc = allocator_type());
copy (3)
set (const set& x);

2.1 构造函数

在 C++ 中,set 容器提供了几种构造函数,适用于不同的使用场景。以下是你提供的构造函数的详细解析:

1. 默认构造函数:empty()

set<int> first();

这是最简单的构造函数,用于创建一个空的 set。它初始化一个没有任何元素的集合。此构造函数会使用默认的比较器(key_compare)和分配器(allocator_type。这种构造方式适合在后续添加元素时使用。

2. 范围构造函数:range()

template <class InputIterator>
set(InputIterator first, InputIterator last, 
    const key_compare& comp = key_compare(), 
    const allocator_type& alloc = allocator_type());
	int myints[] = { 10,20,30,40,50 };
	std::set<int> second(myints, myints + 5);        // range

范围构造函数允许你通过指定一个元素范围来创建 set。通过提供一对迭代器 [first, last],可以将一段容器(如 vector 或数组)的元素拷贝到 set 中。

此构造函数会使用提供的 key_compare 来进行元素的排序,以及使用 allocator_type 来进行内存分配。如果未提供这两个参数,则会使用默认的比较器和分配器

3. 拷贝构造函数:copy()

set(const set& x);

拷贝构造函数会通过复制另一个 set 来创建一个新的 set。它会复制整个元素集合,并保持相同的排序规则和内存分配方式。当你想要创建一个与另一个 set 内容相同的新 set 时,这个构造函数非常有用。

	std::set<int> third(second);

2.2 默认比较器和默认分配器

在 C++ 中,set 容器的默认比较器和分配器分别是:

1. 默认比较器(key_compare

set 是一个基于平衡二叉搜索树(通常是红黑树)的容器,元素会根据某种顺序进行排序。默认情况下,set 使用 std::less<T> 作为比较器,Tset 存储元素的类型。

  • std::less<T>:是一个函数对象(也叫谓词),其作用是如果左侧的元素小于右侧的元素,则返回
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值