我们知道STL中我们常用的setmultisetmapmultimap都是基于红黑树。本文介绍了它们的在STL中的底层数据结构_Rb_tree的直接用法与部分函数。难点主要是_Rb_tree的各个参数的确定。

特别注意在如下代码的Selector类用于从Node中选出用于排序的key值,这个仿函数必须返回const int&而不能是int,否则less<int>::operator(const int&, const int&)会抛出segmentation fault。由于源码中逻辑比较复杂,但是可以观察到内部涉及这方面的地方经常使用到指针。所以可以推测是因为引用了已经释放的局部变量所以才抛出的segmentation fault。一开始写成int,看了很多源码才发现是这个原因,一定要注意。

接下来是样例代码,里面都有注释了。

#include <iostream>
#include <iomanip> // 原则上不要直接引用这个头文件,这里只是为了测试
#include <bits/stl_tree.h> using namespace std; struct Node {
int first, second;
Node(int _first, int _second) : first(_first), second(_second){}; friend ostream& operator<<(ostream& outs, const Node& node) {
outs << '{' << node.first << ',' << node.second << '}';
return outs;
}
}; template <class T>
struct Selector {
// MUST return const int&, not int.
// if return int, segmentation fault will occur.
// I have spent much time because of this.
const int& operator()(const T& obj) const {
return obj.first;
}
}; int main() {
// _Rb_tree: red-black tree in STL.
using tree_type = _Rb_tree<int, Node, Selector<Node>, less<int>>;
using iterator_type = tree_type::iterator;
using result_pair_type = pair<tree_type::iterator, bool>;
tree_type tree; // 插入元素Node(1, 2)
result_pair_type res = tree._M_insert_unique(Node(1, 2));
cout << "insert address = " << res.first._M_node << endl;
cout << "insert result = " << boolalpha << res.second << endl; // true iterator_type it = tree.begin();
cout << "begin address = " << it._M_node << endl; it = tree.find(1);
cout << "address = " << it._M_node << ", value = " << *it << endl; // 再插入元素Node(1, 2)但是因为调用的是insert_unique
// 它不会添加重复值,所以插入会被拒绝
res = tree._M_insert_unique(Node(1, 2));
cout << "insert result = " << boolalpha << res.second << endl; // false // 再插入元素Node(1, 2)但这次调用insert_equal
// multiset和multimap就是利用这个函数来插入重复值
// 也就是这个函数允许重复值,所以插入成功
tree._M_insert_equal(Node(1, 3));
cout << "size = " << tree.size() << endl; // 大小就变为2 pair<iterator_type, iterator_type> result = tree.equal_range(1);
for (iterator_type ite = result.first; ite != result.second; ++ite) {
cout << "address = " << ite._M_node << ", value = " << *ite << endl;
} return 0;
}

程序的输出为(内存地址不定):

insert address = 0xf91be0
insert result = true
begin address = 0xf91be0
address = 0xf91be0, value = {1,2}
insert result = false
size = 2
address = 0xf91be0, value = {1,2}
address = 0xf91c10, value = {1,3}

STL中_Rb_tree的探索的更多相关文章

  1. C++的STL中vector内存分配方法的简单探索

    STL中vector什么时候会自动分配内存,又是怎么分配的呢? 环境:Linux  CentOS 5.2 1.代码 #include <vector> #include <stdio ...

  2. STL中的set容器的一点总结

    1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...

  3. STL中的next_permutation

    给定一个数组a[N],求下一个数组. 2 1 3 4 2 1 4 3 2 3 1 4 2 3 4 1 ..... 在STL中就有这个函数: 1.参数是(数组的第一个元素,数组的末尾),注意这是前闭后开 ...

  4. 3.2 STL中的函数对象类模板

    *: STL中有一些函数对象类模板,如下所示: 1)例如要求两个double类型的x 和y 的积,可以: multiplies<double>()(x,y); 该表达式的值就是x*y的值. ...

  5. C++的模板特化 和 STL中iterator_traits模板的偏特化

    C++中有类模板和函数模板,它们的定义如下所示: 类模板: template<class T1,class T2> class C { //... }; 函数模板: template< ...

  6. C++ STL中vector(向量容器)使用简单介绍

    原文:http://www.seacha.com/article.php/knowledge/cbase/2013/0903/2205.html C++ vector(向量容器)是一个线性顺序结构.相 ...

  7. 深入了解STL中set与hash_set,hash表基础

    一,set和hash_set简介 在STL中,set是以红黑树(RB-Tree)作为底层数据结构的,hash_set是以哈希表(Hash table)作为底层数据结构的.set可以在时间复杂度为O(l ...

  8. 【转】 STL中的set容器的一点总结

    1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...

  9. C++ STL中Map的按Key排序和按Value排序

    map是用来存放<key, value>键值对的数据结构,可以很方便快速的根据key查到相应的value.假如存储学生和其成绩(假定不存在重名,当然可以对重名加以区 分),我们用map来进 ...

随机推荐

  1. k8s pod时区更改

    一.问题所在 在K8S里启动一个容器,该容器的设置的时区是UTC0,但是对于很多客户而言,其主机环境并不在UTC0.例如中国客户在UTC8.如果不把容器的时区和主机主机设置为一致,则在查找日志等时候将 ...

  2. 获取出口IP地址

    curl https://www.ipaddress.com/ |grep "My IPv4 Address" # 推荐 curl icanhazip.com curl www.t ...

  3. 2Nginx+keepalive+2tomcat 故障转移

    根据真实生产环境 总结. 硬件:共计2台Linux服务器  76和77  每台服务器都安装 Nginx  Keepalive  Tomcat80作为虚拟ip,负责对外连接.   78和79是两台mys ...

  4. JMeter接口测试-提取动态列表最后一个值的两种方法

    前言 在用JMeter做接口测试时,我们经常会遇到,一个接口返回一个json串,在这个json串中,某个节点的值是一个列表,而且这个列表的长度是动态变化的.今天我们来学习两种提取动态列表最后一个值的两 ...

  5. .NET Core之单元测试(四):Fluent Assertions的使用

    目录 什么是Fluent Assertions 待测试API 测试用例 什么是Fluent Assertions Fluent Assertions 是 .NET 平台下的一组扩展方法,用于单元测试中 ...

  6. B树(B-树) 、B+树

    B树(B-树) 1.B-树(B树)的基本概念B-树中所有结点中孩子结点个数的最大值成为B-树的阶,通常用m表示,从查找效率考虑,一般要求m>=3.一棵m阶B-树或者是一棵空树,或者是满足以下条件 ...

  7. Nginx三大主要功能

    1.做静态资源服务器,可以用于前端项目发布,图片文件文件等静态服务器. 2.做反向代理服务器,域名往往配置在Nginx上,真正的业务服务器躲在其身后. 3.做负载均衡服务器,作为负载集群的入口网关. ...

  8. 初窥ECharts

    近来趁着空闲时间了解了一下 ECharts.也顺带记录一番. 首先要从下载ECharts库,这个从官网可以直接下载. 引入ECharts.JS <head> <meta charse ...

  9. SAP MM 采购订单与相关合同的价格差异问题分析

    SAP MM 采购订单与相关合同的价格差异问题分析 笔者所在的项目里,一般生产性物料PO的价格是来自于合同价格的,而合同的价格来自于采购信息记录的价格,业务部门不允许PO里随便改价格的. 但是业务部门 ...

  10. 关系模式范式分解教程 3NF与BCNF口诀

    https://blog.csdn.net/sumaliqinghua/article/details/86246762 [通俗易懂]关系模式范式分解教程 3NF与BCNF口诀!小白也能看懂原创置顶 ...