先决条件:具有STL和Sets Data结构的基本知识。
关于订购的安排
有序集是g ++中基于策略的数据结构,可将唯一元素保持在已排序的顺序中。它以log(n)复杂度执行由STL中的set数据结构执行的所有操作,还以log(n)复杂度执行两个附加操作。
- order_of_key(k) :严格小于k的项目数。
- find_by_order(k) :集合中的第K个元素(从零开始计数)。
实现有序集所需的头文件及其描述
为了实现ordered_set,GNU C++库包含其他基于Policy的数据结构,我们需要包括:
- // Common file
include - // Including tree_order_statistics_node_update
include
第一个用来包含关联的容器或模板组,例如set,multimap,map等。此标头文件中提供了下面将要使用的基于树的数据结构。
第二个头文件用于包含tree_order_statistics_node更新,如下所述:
using namespace __gnu_pbds;
它是基于GNU的基于Policy的数据结构所必需的命名空间。
基于树的容器具有具体的结构,但是有序集实现所需的必要结构是:
tree < int , null_type , less , rb_tree_tag , tree_order_statistics_node_update >
- int :是我们要插入的数据类型(KEY),可以是整数,浮点数或成对的int等。
- null_type :这是映射的策略。此处将其用作集合为null。如果我们要获取map而不是集合,则必须使用第二个参数类型为mapd type。
- less :这是比较两个功能的基础。
- rb_tree_tag :使用的树的类型。通常是红黑树,因为它需要log(n)的时间来进行插入和删除,而其他时间则需要线性时间,例如splay_tree。
- tree_order_statistics_node__update :它包含在tree_policy.hpp中,并且包含用于更新基于树的容器的节点变量的各种操作,因此我们可以跟踪元数据,例如子树中的节点数
有序集合中除集合外的其他功能
与集合的先前操作一起,它支持两个主要的重要操作
- find_by_order(k) :它在O(logn)时间中返回集合中第k个元素(从零开始计数)的迭代器。要找到第一个元素k必须为零。
让我们假设我们有一个集合s:{1、5、6、17、88},然后:
*(s.find_by_order(2)):集合中的第三个元素,即6
*(s.find_by_order(4)):集合中的第5个元素,即88 - order_of_key(k) :它返回在O(logn)时间内严格小于我们的项目k的项目数。
让我们假设我们有一个集合s:{1、5、6、17、88},然后:
s.order_of_key(6):严格小于6的元素数为2。
s.order_of_key(25):严格小于25的元素数为4。
集合与有序集合之间的差异
集合和有序集合之间没有太大的区别,尽管有序集合可以假定为集合的扩展版本,能够执行在竞争性编程中广泛使用的一些更高级的功能(如上所述)。
注意: ordered_set在此处用作给tree
实际应用:
假设有一种情况,即元素在数组中一个接一个地插入,并且在每次插入之后,给定范围[l,r],我们必须确定数组中大于等于l且小于等于l的元素数比等于r。最初,该数组为空。
例子:
Input : 5
1 2
1
2 5
2
1 5
Output : 0
1
3
解释:
- 最初,数组为空
- 插入了5个。
- 大于等于1且小于等于2的元素计数为0。
- 插入1。
- 大于等于2且小于等于5的元素计数为1,即5。
- 2已插入。
- 大于等于1且小于等于5的元素数为3,即5、1、2。
Input : 1
1 2
2
3 5
5
1 4
Output : 1
0
2
- 插入1。
- 大于等于1且小于等于2的元素计数为1,即1。
- 2已插入。
- 大于等于3且小于等于5的元素计数为0。
- 插入了5个。
- 大于等于1且小于等于4的元素计数为2,即1、2。
如果我们在STL中使用set在set上查找upper_bound,则它仅给出元素的地址,并且我们只能使用解引用运算符(*)来找到该地址处的值。
假设我们有一个{0,1,2,7,8,20}的集合,并且发现upper_bound为2,那么它返回一个与元素在集合中的位置相对应的地址(在本例中为7),不能减去集合(s.begin())的起始地址,以找到小于2的元素数量(如矢量一样)。
因此,这里需要有序集。注意:可以借助其他一些逻辑和数据结构来实现上述功能,但是使用有序集可使代码紧凑,并且可以轻松,快速地实现。
执行有序集
// C++ program to demonstrate the // ordered set in GNU C++ #include
using namespace std; // Header files, namespaces, // macros as defined above #include #include using namespace __gnu_pbds; #define ordered_set tree , rb_tree_tag,tree_order_statistics_node_update> // Driver program to test above functions int main() { // Ordered set declared with name o_set ordered_set o_set; // insert function to insert in // ordered set same as SET STL o_set.insert(5); o_set.insert(1); o_set.insert(2); // Finding the second smallest element // in the set using * because // find_by_order returns an iterator cout << *(o_set.find_by_order(1)) << endl; // Finding the number of elements // strictly less than k=4 cout << o_set.order_of_key(4) << endl; // Finding the count of elements less // than or equal to 4 i.e. strictly less // than 5 if integers are present cout << o_set.order_of_key(5) << endl; // Deleting 2 from the set if it exists if (o_set.find(2) != o_set.end()) o_set.erase(o_set.find(2)); // Now after deleting 2 from the set // Finding the second smallest element in the set cout << *(o_set.find_by_order(1)) << endl; // Finding the number of // elements strictly less than k=4 cout << o_set.order_of_key(4) << endl; return 0; } 输出
2 2 2 5 1
因此,我们现在可以轻松地解决上述问题,即可以通过以下方式找到介于l和r之间的元素数:
o_set.order_of_key(r + 1)– o_set.order_of_key(l)注意:由于该集合仅包含UNIQUE元素,因此要对具有重复元素的数组执行操作,我们可以将KEY视为一对元素,而不是整数,其中第一个元素是我们数组的必需元素,而只有整数该对中的第二个元素必须是唯一的,以便整个对都是唯一的。
有关更多详细信息,请参阅:
https://gcc.gnu.org/onlinedocs/libstdc++/manual/policy_data_structures.html如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。
最初,数组为空