红黑树入门篇

红黑树

前言:

  1. JDK1.7时,HashMap组成:数组+链表。到1.8后,推出了红黑树。

当链表长度超过阈值8,则会将链表转化为红黑树,当小于6时,就会将红黑树转化为链表。

  1. 由于二叉查找树的性能极低,所以红黑树自然而然就占据主要地位。

时间复杂度也就是树的深度。

链表(也称暴力O(n))->二叉树->二叉查找树(O(logn)~O(n))->特殊的二叉查找树(红黑树O(logn))

hash的时间复杂度为O(1)效率最高。但是存在诸多问题,所以尽量不要使用

红黑树的性质:

  1. 每个结点不是红色就是黑色。
  2. 不可能有连在一起的红色结点。
  3. 根节点都是黑色。
  4. 每个红色结点的两个子节点都是黑色。叶子节点都是黑色。

为满足红黑树性质,红黑树有三种变换:

  1. 改变颜色
  2. 左旋

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dwNT8ikB-1582381976086)(assets/1582371575594.png)]

  1. 右旋

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JZcIoA8X-1582381976088)(assets/1582372669417.png)]

变换规则

1、变颜色的情况:

当前结点的父亲是红色,且它的祖父结点的另一个子结点(叔叔结点)也是红色。

1) 把父结点设为黑色。

2)把叔叔结点也设为黑色

3)把祖父也就是父亲的父亲设为红色(爷爷)

4)把指针定义到祖父节点设为当前要操作的分析的点变换规则

在这里插入图片描述

2.左旋:当前父节点是红色,叔叔节点是黑色的时候,且当前的节点是右子树。 ——>左旋:以 父节点 作为根节点 左旋

3.右旋:当前父节点是红色,叔叔节点是黑色的时候,且当前的节点是左子数。 ——>右旋:以 祖父节点 作为根节点 右旋

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mQaiYzu0-1582381976097)(assets/1582371722552.png)]

(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节点的左子树指针
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值