stl源码剖析 详细学习笔记 RB_tree (2)
//---------------------------15/03/22----------------------------
//一直好奇KeyOfValue是什么,查了下就是一个和仿函数差不多的东西,在第7章会详细介绍
//现在只知道KeyOfValue()可以构造一个类调用他的operator()可以得到一个value的key
//允许重复的插入
template<class Key,class Value,
class KeyOfValue,class Compare,
class Alloc>
typename rb_tree<key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_equal(const Value& v)
{
link_type y = header;
link_type x = root();
//从根节点开始搜索直到x为叶子节点
while ( x !=
)
{
y = x;
x = key_compare(KeyOfValue()(v),key(x)) ? left(x) : right(x);
}
//把一个值为v的节点插入x的位置,y是x的父节点
return __insert(x,y,v);
}
//不允许重复
//可以插入(没有重复)返回的bool为true,否则为false
template<class Key,class Value,
class KeyOfValue,class Compare,
class Alloc>
pair<typename rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::iterator,bool>
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::insert_unique(const Value& v)
{
link_type y = header;
link_type x =root();
bool comp =
true;
while( x !=
)
{
y = x;
comp = key_compare(KeyOfValue()(v),key(x));
x = comp ? left(x) :right(x);
}
iterator j = iterator(y);
//最后如果v "小于"(假设比较操作是小于) y
//这边做这样的操作是因为"大于等于"的时候都会向右走,所以需要换一下j.node和v的位置
//看看是否不相等
if(comp)
if(j == begin())
//如果插入点的父节点是最左边的节点
return pair<iterator,bool>(__insert(x,y,v),true);
else
//不是最左边就要--j继续判断
--j;
//这是因为只有最左边可以确定没有比v小的元素了
//如果j.node确实小于v就可以插入。
if(key_compare(key(j.node),KeyOfValue()(v)))
return pair<iterator,bool>(__insert(x,y,v),true);
return pair<iterator,bool>(j,false);
/*
总结下:会出现想等的情况只有有向右走的情况
如果最后是向右走的,那么有可能相等的元素就是j也就是y也就是要插入位置
的父节点
如果最后是向左走的,那么有可能相等的就是比j小的最大的那个元素,也就是--j
*/
}
//__insert
template<class Key,class Value,
class KeyOfValue,class Compare,
class Alloc>
typename rb_tree<key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::
__insert(base_ptr x_, base_ptr y_,const Value& v)
{
link_type x = (link_type) x_;
link_type y = (link_type) y_;
link_type z;
//如果要插入的是根节点或者
要插入的位置不是空(header的左右儿子) 或v小于y 那么就是要插入到左边
if(y == header || x !=
|| key_compare(KeyOfValue()(v),key(y)))
{
z = create_node(v);
left(y) = z; //如果y是header那可以设置leftmost为z
//如果要插入的是根节点,
if(y == header)
{
//设置根节点
root() = z;
//设置最右边的元素
rightmost() = z;
}
//如果要插到最左边
else
if(y == leftmost())
leftmost() = z;
}
else
{
z = create_node(v);
right(y) = z;
if (y == rightmost())
rightmost() = z;
}
//父节点为y左右儿子都是
空。
parent(z) = y;
left(z) =;
right(z) =;
//调整平衡
__rb_tree_rebalance(z,header->parent);
++node_count;
return iterator(z);
}
//旋转以及变色
//平衡这里inline是什么意思?里面明明有循环
而且代码这么长
//下面的代码几乎和算法导论里的一样
inline
void
__rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)
{
x->color = __rb_tree_red;
while(x != root && x->parent->color == __rb_tree_red)
{
if(x->parent == x->parent->parent->left)
{
__rb_tree_node_base* y =x->parent->parent->right;
if(y && y->color == __rb_tree_red)
{
x->parent->color = __rb_tree_black;
y->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_red;
x = x->parent->parent;
}
else
{
if(x == x->parent->right)
{
x = x->parent;
__rb_tree_rotate_left(x, root);
}
x->parent->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_red;
__rb_tree_rotate_right(x->parent->parent, root);
}
}
else
{
__rb_tree_node_base* y =x->parent->parent->left;
if(y && y->color == __rb_tree_red)
{
x->parent->color = __rb_tree_black;
y->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_red;
x = x->parent->parent;
}
else
{
if(x == x->parent->left)
{
x = x->parent;
__rb_tree_rotate_right(x,root);
}
x->parent->color = __rb_tree_black;
x->parent->parent->color = __rb_tree_red;
__rb_tree_rotate_left(x->parent->parent,root);
}
}
}
root->color = __rb_tree_black;
}
//左转
inline voide
__rb_tree_rotate_left(__rb_tree_node_base* x,__rb_tree_node_base*& root)
{
__rb_tree_node_base* y = x->right;
x->right = y->left;
if(y->left !=
)
y->left->parent = x;
y->parent = x->parent;
if(x == root)
root = y;
else
if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
y->parent = y;
}
//右转
inline voide
__rb_tree_rotate_right(__rb_tree_node_base* x,__rb_tree_node_base*& root)
{
__rb_tree_node_base* y = x->left;
x->left = y->right;
if(y->right !=
)
y->right->parent = x;
y->parent = x->parent;
if(x == root)
root = y;
else
if (x == x->parent->right)
x->parent->right = y;
else
x->parent->left = y;
y->right= x;
y->parent = y;
}
//find
template<class Key,class Value,
class KeyOfValue,class Compare,
class Alloc>
typename rb_tree<key, Value, KeyOfValue, Compare, Alloc>::iterator
rb_tree<Key, Value, KeyOfValue, Compare, Alloc>::find(const Key& k)
{
link_type y =header;
link_type x =root();
while(x !=
)
if(!key_compare(key(x), k))
y = x, x =left(x);
else
x = right(x);
iterator j =iterator(y);
return (j ==end() || key_compare(k, key(j.node))) ? end() :j;
}
//最后没有delete操作,之前的算法导论部分已经给出了delete操作
stl源码剖析 详细学习笔记 RB_tree (2)的更多相关文章
- stl源码剖析 详细学习笔记 RB_tree (1)
// // RB_tree_STL.cpp // 笔记 // // Created by fam on 15/3/21. // // #include "RB_tree_STL.h&q ...
- stl源码剖析 详细学习笔记 set map
// // set map.cpp // 笔记 // // Created by fam on 15/3/23. // // //---------------------------15/03 ...
- stl源码剖析 详细学习笔记 hashtable
//---------------------------15/03/24---------------------------- //hashtable { /* 概述: sgi采用的是开链法完成h ...
- stl源码剖析 详细学习笔记heap
// // heap.cpp // 笔记 // // Created by fam on 15/3/15. // // //---------------------------15/03/15 ...
- stl源码剖析 详细学习笔记 空间配置器
//---------------------------15/04/05---------------------------- /* 空间配置器概述: 1:new操作包含两个阶段操作 1>调 ...
- stl源码剖析 详细学习笔记 算法(1)
//---------------------------15/03/27---------------------------- //算法 { /* 质变算法:会改变操作对象之值 所有的stl算法都 ...
- stl源码剖析 详细学习笔记 算法总览
//****************************基本算法***************************** /* stl算法总览,不在stl标准规格的sgi专属算法,都以 *加以标 ...
- stl源码剖析 详细学习笔记 hashset hashmap
//---------------------------15/03/26---------------------------- //hash_set { /* hash_set概述: 1:这是一个 ...
- stl源码剖析 详细学习笔记priority_queue slist
// // priority_queue.cpp // 笔记 // // Created by fam on 15/3/16. // // //------------------------- ...
随机推荐
- Prometheus Node_exporter 之 FileSystem Detail
FileSystem Detail /proc/filesystems 1. Filesystem space available type: GraphUnit: bytesLabel: Bytes ...
- 初识java内存区域
目录: 1.运行时数据区域 2.对象的创建 3.对象的内存布局 4.对象的访问定位 一.运行时数据区域 基本的java虚拟机运行时数据区如下图: 下面我们就来逐个认识这几个运行时的数据区域 1.程序计 ...
- MariaDB实现主从配置及读写分离(一)
一.主从复制方案 1. 在两台CentOS7虚拟机上分别部署MariaDB, 主数据库服务器IP为192.168.17.235, 从服务器IP为192.168.17.238. 从服务器通过调取主服务 ...
- pvr.ccz 与 png 格式 互转的解决方案
pvr.ccz与png互转 pvr是苹果的一种图片格式,我们需要转成png,最简单的办法就是用TexturePacker. 准备工作 TexturePacker :http://www.codeand ...
- JAVA内存管理 [转]
首先我们要明白一点,我们所使用的变量就是一块一块的内存空间!! 一.内存管理原理: 在java中,有java程序.虚拟机.操作系统三个层次,其中java程序与虚拟机交互,而虚拟机与操作系统间交 ...
- 元素视差方向移动jQuery插件-类似github 404页面效果
原文地址:http://www.xuanfengge.com/shake.html 前言: 视差滚动,大家也许并不陌生.但是对于视差方向移动,你是否有见过效果呢?看官请进来瞧瞧~ demo : 轩枫阁 ...
- CSS3 新增的文本属性
一.CSS1&2中的文本属性(W3C标准) text-indent CSS1 检索或设置对象中的文本的缩进 letter-spacing CSS1 检索或设置对象中的文字之间的间隔 word- ...
- python-json模块扩展
sort_keys=True, indent=4, separators=(',', ': ') 格式 json.dumps(response,sort_keys=True, indent=4, se ...
- 广州商学院Python正方教务系统爬虫(获取个人信息成绩课表修改密码)
使用python的requests库简单爬取,使用xpath解析内容 可以获取个人信息.个人照片.成绩单和课表 github地址:https://github.com/PythonerKK/GZCC- ...
- 搭建windows远程节点_jmeter自动化测试环境(接口测试)
WINDOWS10系统下 环境 172.16.0.115虚拟机windows系统作为远程节点. jenkins安装在172.16.0.119:8088虚拟机中. 一.安装配置Java环境 wind ...