知识的学习在于点滴记录,坚持不懈;知识的学习要有深度和广度,不能只流于表面,坐井观天;知识要善于总结,不仅能够理解,更知道如何表达!
红黑树的定义
AVL树为了维护节点平衡,在插入和删除时做了大量的旋转操作,当数据量大了以后,AVL树的旋转操作就拖慢了插入删除的时间,那么红黑树相比于AVL树,插入删除的旋转次数要少了很多,那是因为红黑树并不是一颗绝对平衡的树,它的节点左右子树的高度差不超过2倍(长不超过短的2倍)。
红黑树的性质定义:
1.每一节点都有颜色,不是黑色就是红色
2.根节点root是黑色的
3.叶子节点都是黑色(指叶子节点的地址域null为黑色,一般null节点默认颜色是黑色)
4.不能出现连续的红色节点,也就是说红色节点的孩子节点必须是黑色的
5.从根节点到每一个叶子节点的路径上,黑色节点的数量是一样多的
在进行红黑树的插入删除操作的时候,会涉及节点的旋转和重新着色问题,红黑树的旋转次数要比AVL少很多,插入最多旋转两次,删除最多旋转三次。
像Java的TreeMap,TreeSet,C++的set和map容器,Linux的虚拟内存管理,epoll的内核层实现都应用到了红黑树这种数据结构,其增删查时间复杂度能达到 O ( l o g 2 n ) O(log_2n) O(log2n)。
下面给出红黑树的基本定义:
/**
* 红黑树节点颜色定义
*/
enum COLOR{
BLACK,
RED
}
/**
* 红黑树节点类型定义
* @param <T>
*/
class RBNode<T extends Comparable<T>>{
private T data;
private RBNode<T> left;
private RBNode<T> right;
private RBNode<T> parent;
private COLOR color;
public RBNode(T data, COLOR color) {
this.data = data;
this.color = color;
this.left = this.right = this.parent = null;
}
public RBNode(T data, COLOR color, RBNode<T> parent, RBNode<T> left, RBNode<T> right) {
this.data = data;
this.left = left;
this.right = right;
this.parent = parent;
this.color = color;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public RBNode<T> getLeft() {
return left;
}
public void setLeft(RBNode<T> left) {
this.left = left;
}
public RBNode<T> getRight() {
return right;
}
public void setRight(RBNode<T> right) {
this.right = right;
}
public RBNode<T> getParent() {
return parent;
}
public void setParent(RBNode<T> parent) {
this.parent = parent;
}
public COLOR getColor() {
return color;
}
public void setColor(COLOR color) {
this.color = color;
}
}
/**
* 红黑树定义
* @param <T>
*/
class RBTree<T extends Comparable<T>>{
private RBNode<T> root;
/**
* 获取红黑树节点颜色
* @param node
* @return
*/
private COLOR color(RBNode<T> node){
return node == null ? COLOR.BLACK : node.getColor();
}
/**
* 设置节点颜色
* @param node
* @param color
*/
private void setColor(RBNode<T> node, Color color){
node.setColor(color);
}
/**
* 获取当前节点的父节点
* @param node
* @return
*/
private RBNode<T> parent(RBNode<T> node){
return node.getParent();
}
/**
* 获取node节点的左孩子节点
* @param node
* @return
*/
private RBNode<T> left(RBNode<T> node){
return node.getLeft();
}
/**
* 获取node节点的右孩子节点
* @param node
* @return
*/
private RBNode<T>