红黑树
前言:
- JDK1.7时,HashMap组成:数组+链表。到1.8后,推出了红黑树。
当链表长度超过阈值8,则会将链表转化为红黑树,当小于6时,就会将红黑树转化为链表。
- 由于二叉查找树的性能极低,所以红黑树自然而然就占据主要地位。
时间复杂度也就是树的深度。
链表(也称暴力O(n))->二叉树->二叉查找树(O(logn)~O(n))->特殊的二叉查找树(红黑树O(logn))
hash的时间复杂度为O(1)效率最高。但是存在诸多问题,所以尽量不要使用
红黑树的性质:
- 每个结点不是红色就是黑色。
- 不可能有连在一起的红色结点。
- 根节点都是黑色。
- 每个红色结点的两个子节点都是黑色。叶子节点都是黑色。
为满足红黑树性质,红黑树有三种变换:
- 改变颜色
- 左旋
- 右旋
变换规则
1、变颜色的情况:
当前结点的父亲是红色,且它的祖父结点的另一个子结点(叔叔结点)也是红色。
1) 把父结点设为黑色。
2)把叔叔结点也设为黑色
3)把祖父也就是父亲的父亲设为红色(爷爷)
4)把指针定义到祖父节点设为当前要操作的分析的点变换规则
2.左旋:当前父节点是红色,叔叔节点是黑色的时候,且当前的节点是右子树。 ——>左旋:以 父节点 作为根节点 左旋
3.右旋:当前父节点是红色,叔叔节点是黑色的时候,且当前的节点是左子数。 ——>右旋:以 祖父节点 作为根节点 右旋
(1)把父节点变为黑色
(2)把祖父节点变为红色
(3)以祖父结点旋转
java代码实现
package com.zxm;
/**
* 红黑树原理
*/
public class RedBlackTree {
private final int R = 0; // 红色
private final int B = 1; // 黑色
private Node root; // 红黑树的根节点
class Node{
int data;
int color = R; // 默认插入红色结点
Node left;
Node right;
Node parent;
public Node(int data){
this.data = data;
}
}
// 二叉查找树也就是红黑树的插入过程,不包含变换规则
public void insert(Node root,int data){ // 往root里面插入data数据
if(root.data < data){// 插入的数据比root点要大
if(root.right == null){ // 如果右边没有点,就直接插入。
root.right = new Node(data);
}else {
insert(root.right,data); // 接下来默认root的右结点作为根 继续后面的过程。
}
}else {
if(root.left == null){
root.left = new Node(data);
}else {
insert(root.left,data);
}
}
}
// 左旋
public void leftRotate(Node node){ // 以哪个点作为根左旋
// 1种情况 node就是根节点,也就是root了
if(node.parent == null){
Node E = root;
Node S = E.left;
E.right = S.left;
S.left.parent = E;
E.parent = S;
S.parent = null;
}else {
// 如果有父节点 那么就要操作三个点
if(node == node.parent.left){
node.parent.left=node.right; // 就是把S浮上来变成了新的左子树
}else {
node.parent.right = node.right;
}
node.right = node.right.left; // S点子树指针挂到E点上面去
node.right.left.parent = node; // S点原来的左子树会挂到E上面
node.right.parent = node.parent; // S点上浮,编程E的父节点
node.parent = node.right; // E点的parent会变成原来的S点
node.parent.left = node; // S节点的左子树指针
}
}
}