map,set的底层实现:红黑树[多图,手机慎入]
最近天下有一种颇不太平的感觉,各地的乱刀砍人,到处是贪官服法。京东准备上市了,阿里最近也提交申请了,猎豹也逆袭了,据说猎豹移动在国际市场上表现甚是抢眼。只有屌丝还在写着代码。花开花又谢,花谢花又开,为什么这么多人没有安全感呢?是转型社会给大家带来了浮躁,还是什么?不得而知!
另外,就上一篇文章的问题,还请大家各抒己见!一道面试题:C++相比C#或者java的优势到底在哪里
OK,下面进入今天的主题。红黑树。
我们时候用到了红黑树?
C++STL中map,set的底层实现全是用的红黑树,java,C#等语言同样如此。
为什么需要红黑树?
map,set底层都提供了排序功能,且查找速度快。红黑树实际上是AVL的一种变形,但是其比AVL(平衡二叉搜索树)具有更高的插入效率,当然查找效率会平衡二叉树稍微低一点点,毕竟平衡二叉树太完美了。但是这种查找效率的损失是非常值得的。它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。
何为红黑树?
这里二叉平衡树的概念我就不提了。红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。
操作:
我们知道平衡二叉树要保持他的平衡性,旋转是一项必不可少的工作。同样,红黑树是一颗准平衡二叉树,旋转也是一项重要工作。旋转有向左旋转,向右旋转,左右旋转,右左旋转。其实左右和右左旋转就是左、右旋转的二次使用,我们这里只谈论向左旋转、向右旋转。
树的旋转:


左右旋转的就是上图所示了,代码如下:
void leftRoate(rbTreeNode* x){//左旋转
rbTreeNode* y=x->right;
y->parent=x->parent;
if (x->parent==NULL)
root=y;
x->right=y->left;
if (y->left!=NULL)
y->left->parent=x;
if (x->parent!=NULL&&x->parent->left==x){
x->parent->left=y;
}else if (x->parent!=NULL&&x->parent->right==x){
x->parent->right=y;
}
y->left=x;
x->parent=y;
}
void rightRoate(rbTreeNode* x){//右旋转
rbTreeNode* y=x->left;
x->left=y->right;
y->parent=x->parent;
if (x->parent==NULL)
root=y;
if (x->left!=NULL)
x->left->parent=x;
if (x->parent!=NULL&&x->parent->left==x){
x->parent->left=y;
}else if (x->parent!=NULL&&x->parent->right==x){
x->parent->right=y;
}
y->right=x;
x->parent=y;
}
红黑树的插入:
一直搜查到叶子节点X,X的父节点会出现以下几种情况:
1、父节点是空,或者父节点的颜色是黑色。直接插入。
2、父节点是红色:
1)父节点是爷爷结点的左结点
a,叔叔结点存在,且是红色
b,叔叔结点不存在,或者是黑色
2)父节点是爷爷结点的右孩子
c,叔叔结点存在且也为红色
d,叔叔结点不存在,或者为黑色。

第二种情况:

红黑树的插入操作就是上图所示:代码如下,
void keepRBTreeBlance(rbTreeNode* x,rbTreeNode* y){
x->color=red;
while(x!=NULL&&x->parent!=NULL&&x->parent->color==red){//父节点是红色
if (x->parent==x->parent->parent->left){//父节点是爷爷结点的左节点
rbTreeNode* z=x->parent->parent->right;//叔叔结点
if(z&&x->parent->color==red){//叔叔结点存在,且也为红色。父和叔都置黑,爷爷置红。
x->parent->color=black;//父置黑
z->color=black;//shushu置黑
x->parent->parent->color=red;//爷爷置红
x=x->parent->parent;
}else{//叔叔结点时黑色或者叔叔结点不存在的情况。
if (x==x->parent->right){//////........................问题
//rbTreeNode* temp=x;
x=x->parent;
leftRoate(x);
}
x->parent->color=black;
x->parent->parent->color=red;
rightRoate(x->parent->parent);
}
}else if (x->parent==x->parent->parent->right){//父节点是爷爷结点的右节点
rbTreeNode* z=x->parent->parent->left;//叔叔结点
if (z&&z->color==red){//都是红色
x->parent->color=black;//父置黑
z->color=black;//shushu置黑
x->parent->parent->color=red;//爷爷置红
x=x->parent->parent;
}else{
if (x==x->parent->left){//如果是左孩子,需要一次右转身跳投
x=x->parent;
rightRoate(x);
}
x->parent->color=black;//同时改变颜色。
x->parent->parent->color=red;
leftRoate(x->parent->parent);
}
}
}
root->color=black;
}
bool insertRBTree(elemType elemValue){
rbTreeNode* y=header;
rbTreeNode* x=root;
while(x!=NULL){
y=x;
if (elemValue>x->data){//elemValue大于该节点的值,转右子树
x=x->right;
}else if (elemValue<x->data){//elemValue小于该节点的值,转左子树
x=x->left;
}else if (elemValue==x->data){//有相等的直接返回false
return false;
}
}
rbTreeNode* z=new rbTreeNode();
z->data=elemValue;
if (y==header){//空直接插入
z->color=black;
root=z;
return true;
}else{
if (y->data>elemValue)
y->left=z;
else
y->right=z;
}
z->parent=y;
keepRBTreeBlance(z,y);
return true;
}
红黑树的删除操作类似于B-树的删除,需要注意保持它的红黑平衡性。红黑的搜索那就和B-树的查找一模一样了,其实任何排序树的操作都是一样的。比如下面将要讲到的B+树。
B树系列还有一篇是B+树,敬请期待。
参考文献:STL源码剖析、百度。
版权所有,欢迎转载,但是转载请注明出处:潇一
map,set的底层实现:红黑树[多图,手机慎入]的更多相关文章
- stl map底层之红黑树插入步骤详解与代码实现
转载注明出处:http://blog.csdn.net/mxway/article/details/29216199 本篇文章并没有详细的讲解红黑树各方面的知识,只是以图形的方式对红黑树插入节点需要进 ...
- TreeMap 底层是红黑树 排序是根据key值进行的 添加元素时异常 Comparable异常 Comparator比较自定义对象放在键的位置
package com.swift; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; ...
- stl vector、红黑树、set、multiset、map、multimap、迭代器失效、哈希表(hash_table)、hashset、hashmap、unordered_map、list
stl:即标准模板库,该库包含了诸多在计算机科学领域里所常用的基本数据结构和基本算法 六大组件: 容器.迭代器.算法.仿函数.空间配置器.迭代适配器 迭代器:迭代器(iterator)是一种抽象的设计 ...
- 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法
==学习目标== 1.能够了解红黑树 2.能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构) 3.能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历) 4.能够掌 ...
- map,hash_map, hash_table, 红黑树 的原理和使用
在刷算法题的时候总是碰到好多题,号称可以用hash table来解题.然后就蒙圈了. 1.首先,map和hash_map的区别和使用: (1)map底层用红黑树实现,hash_map底层用hash_t ...
- TreeMap:是基于红黑树的Map接口的实现
> TreeMap:是基于红黑树的Map接口的实现. 红黑树:平衡二叉树 取出时,可以有三种方式:前序遍历,中序遍历,后序遍历 >排序: A 自然排序 --TreeMap无参构造 Tre ...
- 【深入理解Java集合框架】红黑树讲解(上)
来源:史上最清晰的红黑树讲解(上) - CarpenterLee 作者:CarpenterLee(转载已获得作者许可,如需转载请与原作者联系) 文中所有图片点击之后均可查看大图! 史上最清晰的红黑树讲 ...
- 【算法】通过TreeMap理解红黑树
本文以Java TreeMap为例,从源代码层面,结合详细的图解,剥茧抽丝地讲解红黑树(Red-Black tree)的插入,删除以及由此产生的调整过程. 总体介绍 Java TreeMap实现了So ...
- TreeMap红黑树
Java TreeMap实现了SortedMap接口,也就是说会按照key的大小顺序对Map中的元素进行排序,key大小的评判可以通过其本身的自然顺序(natural ordering),也可以通过构 ...
随机推荐
- asp.net MVC4 @Html.DropDownList的使用
在MVC4中使用Razor语法,一使用就爱上他了, 一般项目都是有一些增删改查功能,表单下拉框是经常使用的,除了用原始的<select>外,还可以用@Html.DropDownList和@ ...
- bzoj 4568 [SCOI 2016] 幸运数字
题目大意 给定一棵\(n\)个点的树,每个点有权值 \(q\)次询问树上路径中 每个点权值可选可不选的最大异或和 \(n\le 2*10^4,q\le 2*10^5,val[i]\le 2^{60}\ ...
- 【刷题】HDU 4405 Aeroplane chess
Problem Description Hzz loves aeroplane chess very much. The chess map contains N+1 grids labeled fr ...
- 【以前的空间】bzoj 1072 [SCOI2007]排列perm
又颓废了一个下午,最近撸mc撸到丧失意识了,玩的有点恶心,于是找水题做,瞧不起颓废的自己啊. another水题. 这题题意很明显啦,就是找数字排列后组成的数去mod d=0后有多少种. 普通的搜索的 ...
- [NOI2009]管道取珠 DP + 递推
---题面--- 思路: 主要难点在思路的转化, 不能看见要求$\sum{a[i]^2}$就想着求a[i], 我们可以对其进行某种意义上的拆分,即a[i]实际上可以代表什么? 假设我们现在有两种取出某 ...
- POJ1816:Wild Words——题解
http://poj.org/problem?id=1816 比较麻烦的trie. 首先你需要选择针对n还是m建立trie,这里我选择了针对n. 那么就需要面临卡空间的问题. 这里提供了一种链式前向星 ...
- BZOJ 1016 Windy 数 | 数位DP
题目: http://www.lydsy.com/JudgeOnline/problem.php?id=1026 题解: f[i][j][1/0]表示枚举到第i位,这位开头是j,当前的数大于(1)或小 ...
- [Leetcode] Sum root to leaf numbers求根到叶节点的数字之和
Given a binary tree containing digits from0-9only, each root-to-leaf path could represent a number. ...
- 理解LINUX LOAD AVERAGE的误区
一直不解,为什么io占用较高时,系统负载也会变高,偶遇此文,终解吾惑. uptime和top等命令都可以看到load average指标,从左至右三个数字分别表示1分钟.5分钟.15分钟的load a ...
- bzoj 4402 Claris的剑 组合数学
Claris的剑 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 375 Solved: 213[Submit][Status][Discuss] D ...