基本操作及Java代码实现-红黑树-数据结构和算法

基本操作及Java代码实现-红黑树-数据结构和算法

目录




内容

上面一篇介绍了红黑树的概念、特征和时间复杂度,这里我们进一步讲解红黑树的基础操作和Java代码实现。

数据结构基本操作添加、修改、删除、查询,红黑树做为一种特殊的二叉查找树,其查找和修改同二叉查找树;但是添加、删除和二叉查找树有很大区别。

道理很简单,添加或删除红黑树中的节点之后,红黑树就发生了变化,可能不满足红黑树的5条性质,也就不再是一颗红黑树了,而是一颗普通的树。而通过旋转,可以使这颗树重新成为红黑树。简单点说,旋转的目的是让树保持红黑树的特性。

所有Java代码基本参照HashMap TreeNode完成。

1、红黑树构建

1.1、红黑树的节点分析

红黑树作为一种数据结构,基本功能-存储数据;作为二叉树,有左右子树(节点);具有自己独特的特点,每个节点都有颜色;为了方便查找某个节点的父级节点,用一个指针指向它 的父节点;

  • 红黑树节点Java代码
static final class RBNode<K, V> {
        final K key; // 关键字
        V value; // 数据
        boolean red; // 是否是红色

        private RBNode<K, V> parent; // 父节点指针
        private RBNode<K, V> left; // 左子节点指针
        private RBNode<K, V> right; // 右子节点指针
		
		// 构造函数
        public RBNode(K key, V value, boolean red, RBNode<K, V> parent, RBNode<K, V> left, RBNode<K, V> right) {
            this.key = key;
            this.value = value;
            this.red = red;
            this.parent = parent;
            this.left = left;
            this.right = right;
        }

		/**
		* 以当前节点起始,查找根节点
		*/
        final RBNode<K,V> root() {
            for (RBNode<K,V> r = this, p;;) {
                if ((p = r.parent) == null)
                    return r;
                r = p;
            }
        }
    }

1.2、 红黑树成员变量

要查看红黑树,需要有一个切入点,就是红黑树的根节点;想要指定存储了几个元素,需要size变量。

1.3、红黑树的基本操作

  • 左旋
  • 右旋
  • 插入
  • 插入后平衡跳转
  • 删除
  • 删除后平衡跳转
  • 判断是否为空
  • 获取元素个数
  • 打印
  • 查找(根据节点key)

1.4、红黑树类代码

完整代码在最后仓库地址。

2.变色

因为上面我设计用布尔值存储节点的颜色信息,这个很容易实现,通过设置true,节点为红色;false,节点为黑色。
图示:
在这里插入图片描述

3、左旋

  • 旋转过程图示:在这里插入图片描述

  • 步骤

  1. 对目标节点p向左旋转(逆时针)
  2. p节点右节点r的左节点rl 成为 p的右节点,如果rl不为空,rl的父节点变为p节点
  3. p的父节点pp变为r的父节点,如果pp为空,则说明原p为根节点,现在根节点root指向r
  4. 如果p为pp的左节点,则pp的左节点设置为r;否则pp的右节点设置为r。
  5. p的父节点变为r,r的左节点变为p
  • 代码实现
 // 左旋
    static <K, V> RBNode<K, V> rotateLeft(RBNode<K, V> root, RBNode<K, V> p) {
        RBNode<K, V> r, pp, rl;
        if (p != null && (r = p.right) != null) {
            if ((rl = p.right = r.left) != null)
                rl.parent = p;
            if ((pp = r.parent = p.parent) == null)
                (root = r).red = false;
            else if (pp.left == p)
                pp.left = r;
            else
                pp.right = r;
            r.left = p;
            p.parent = r;

        }
        return root;
    }

3、右旋

  • 旋转过程图示:在这里插入图片描述

  • 步骤

  1. 对目标节点p向右旋转(顺时针)
  2. p节点左节点l的右节点lr 成为 p的左节点,如果lr不为空,lr的父节点变为p节点
  3. p的父节点pp变为l的父节点,如果pp为空,则说明原p为根节点,现在根节点root指向l
  4. 如果p为pp的左节点,则pp的左节点设置为l;否则pp的右节点设置为l。
  5. p的父节点变为pl,pl的左节点变为p
  • 代码实现
 // 右旋
    static <K, V> RBNode<K, V> rotateRight(RBNode<K, V> root, RBNode<K, V> p) {
        RBNode<K, V> l, pp, lr;
        if (p != null && (l = p.left) != null) {
            if ((lr = p.left = l.right) != null)
                lr.parent = p;
            if ((pp = l.parent = p.parent) == null)
                (root = l).red = false;
            else if (pp.left == p)
                pp.left = l;
            else pp.right = l;
            l.right = p;
            p.parent = l;

        }
        return root;
    }

后记

  欢迎交流,本人QQ:806797785

项目源代码地址:https://gitee.com/gaogzhen/algorithm.git
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaog2zh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值