为啥要有红黑树

上一章我们聊到了二叉查找树数,但是二叉查找树在 插入的时候 如果 递增插入或者递减插入 ,就会导致这个棵树 单边倾斜,或者说单边增长从而退化成链表而影响查询效率,如下图

从而引进了红黑树来解决此类问题,那么红黑树是怎么解决的呢?,红黑树中有一些平衡化的机制,可以在插入的时候尽量两边高度一直 趋近于一颗平衡二叉树;

下面是左倾红黑树的定义:

  1. 节点是红色或黑色;
  2. 根节点是黑色;
  3. 所有叶子节点是黑色;(叶子节点是NULL节点)
  4. 每个红色节点的两个子节点都是黑色;(从根节点到每个叶子节点的路径上不能有两个连续的红节点)
  5. 从任何一个节点到每个叶子节点的所有路径都包含相同数目的黑色节点;
  6. 红色节点像左倾斜

基于红黑数定义:我来看一下,插入时可能出现的情况:

第一总情况:

第二种情况:

case2: 不满足 (不能有两个连续的红色节点)  可见 通过右旋  达到了从树搞为 3 变成了树搞为2的树

第三种情况

case3: 一个节点不能有两个红色节点相连

除了这些平衡化的操作其实和我们的二叉查找树没有什么差别,我们直接撸代码实现;

package com.data.structure;import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingDeque;/*** 作者: 贺伟* 时间: 2021/3/25* @param <K>* @param <V>*/
public class RedBlackTree<K extends  Comparable,V> {//节点个数private int nodeCount;//根节点private Node<K,V>  root;//定义true为红色private  static  boolean   RED=true;//false为黑色private  static  boolean   BLACK=false;class  Node<K extends  Comparable,V>{//左子树Node<K,V> left;//右子树Node<K,V>  right;//该树的颜色;boolean color;//存入的keyK key;//存入的valueV value;public Node(Node<K, V> left, Node<K, V> right, boolean color, K key, V value) {this.left = left;this.right = right;this.color = color;this.key = key;this.value = value;}}/*** 左旋**        A            B*      /  \RED  red  / \*          B    ==> A*         / \      / \**/public  Node  leftReversal( Node A){//取出B节点Node B = A.right;//让B的左子节点成为A的右子节点A.right=B.left;//让 B节点作为A的右子节点B.left=A;//让A的颜色等于B 的颜色B.color =A.color;//让A的颜色为红色A.color=RED;//返回新的根节点return  B;}/****  右旋**         c                      B*    RED / \               RED /  \ RED*      B       =======>      A     C* RED/ \                    / \   / \*   A*  / \**/public   Node   rightReversal( Node C){//取出B节点Node B = C.left;//让B的 右子节点成为 C 的左子节点C.left= B.right;//让C的 成为 B 的 右子节点B.right=C;//让b的颜色等于c的颜色C.color =B.color;//让b为黑色B.color= BLACK;//返回Breturn  B;}/***  变色   |                 | 红色*        B                 b*    red/ \ red ==> BLACK / \ BLACK*     a    c            a   c***/public  void   changeColor(Node B){//让b为黑色B.color=RED;//让a为红色B.left.color=BLACK;//让c为红色B.right.color=BLACK;}/*** 根据key获取Value*/public  V  get(K key){return getValue(root,key);}private V getValue(Node<K,V> root, K key) {if (root==null){return  null;}//获取当前节点key与 查找key的比较值int  com=key.compareTo(root.key);if (com>0){//如果查询key大于当前的key 就从右边找return   getValue( root.right,key);}else if (com<0){//如果查询的key小于当前的key, 就从左边找return   getValue( root.left,key);}else {//key相等说明找到了return root.value;}}/*** 向当前树中插入一个 新的子树*/public  void   put(K key, V value ){root= putValue(root,key,value);//根节点颜色始终为黑色root.color=BLACK;}//递归插入一个子树private Node<K,V> putValue(Node<K,V> root, K key, V value) {if (root==null){nodeCount++;//如果当前节点为空 插入一个颜色为红色的新节点return new Node<>(null,null,RED,key,value);}//获取当前节点key与 查找key的比较值int  com=key.compareTo(root.key);if (com>0){//从右边插入root.right=putValue(root.right,key,value);}else if (com<0) {//从左边插入root.left=putValue(root.left,key,value);}else {//修改当前的值(覆盖value)root.value=value;}//判断是否需要左旋if (isRED(root.right)&&!isRED(root.left)){root=leftReversal(root);}//判断是否需要右旋if (isRED(root.left)&&isRED(root.left.left)){root=rightReversal(root);}//判断是否需要变色if (isRED(root.left)&&isRED(root.right)){changeColor(root);}return  root;}//判断当前颜色节点颜色是否为红色public  boolean  isRED(Node node){if (node==null||node.color==BLACK){return BLACK;}else {return RED;}}//获取当前树非空节点个数public  int getSize(){return  nodeCount;}//获取层序遍历结果public List<Node<K,V>> layerItemList() throws Exception {if (root==null){//返回空集合return null;}java.util.Queue<Node<K, V>> nodeQueue = new LinkedBlockingDeque();;//把根节点入队nodeQueue.add(root);//准备一个list 取出层序遍历的结果List  list=new ArrayList();//如果队列不为空则继续循环while (!nodeQueue.isEmpty()){//出队Node<K, V> current = nodeQueue.poll();//把出队元素加入list中list.add(current);System.out.println( current.key+": " +current.value);if (current.left!=null){//左节点入队nodeQueue.add(current.left);}if (current.right!=null){//右节点入队nodeQueue.add(current.right);}}return list;}public  void  itemPrint() throws Exception {this.layerItemList();}}

我们来测试一下看下数据能不能正常读出来,并且顺序是否一样

package com.student;import com.data.structure.*;public class demo {public static void main(String[] args) throws Exception {RedBlackTree<Integer, String> redBlackTree = new RedBlackTree<>();redBlackTree.put(5,"张三");redBlackTree.put(3,"李四");redBlackTree.put(7,"王五");redBlackTree.put(4,"赵六");System.out.println("该树的节点个树:"+ redBlackTree.getSize());System.out.println("get方法取出的数据");System.out.println(redBlackTree.get(5));System.out.println(redBlackTree.get(3));System.out.println(redBlackTree.get(7));System.out.println(redBlackTree.get(4));System.out.println("层序遍历后的结果");redBlackTree.itemPrint();}
}

看一下测结果:

可见都取出来了,我看一下树的层序遍历结果,在画图模拟一下插入的过程,反推树是否一样:

所以最后层结果应该是  5473  和测试结果一致,完美结束,各位大佬评论区见

数据结构之 红黑树(左倾红黑树) java实现相关推荐

  1. 红黑树进阶—左倾红黑树(LLBR)介绍

    红黑树已经有很长的历史,在许多现代编程语言的符号表中都有使用,但是其缺点也很明显,其代码实现过于繁杂.因此出现的红黑树的修改版--左倾红黑树 左倾红黑树的代码实现相比于典型的红黑树来说要简单不少,但是 ...

  2. java 二叉树 红黑树_常见数据结构(二)-树(二叉树,红黑树,B树)

    常见数据结构(二)-树(二叉树,红黑树,B树) 标签: algorithms [TOC] 本文介绍数据结构中几种常见的树:二分查找树,2-3树,红黑树,B树 写在前面 本文所有图片均截图自course ...

  3. 数据结构——左倾红黑树

    左倾红黑树 前提了解 红黑树和平衡多叉树的对应关系 左倾红黑树 基于自顶向下2-3-4树的左倾红黑树 基于2-3树的左倾红黑树 重要代码 左右旋转变色 翻转变色 向2-3左倾红黑树插入 向2-3-4左 ...

  4. 红黑树+java+删除_红黑树深入剖析及Java实现

    红黑树是平衡二叉查找树的一种.为了深入理解红黑树,我们需要从二叉查找树开始讲起. BST 二叉查找树(Binary Search Tree,简称BST)是一棵二叉树,它的左子节点的值比父节点的值要小, ...

  5. 【数据结构和算法05】 红-黑树(转发)

    2019独角兽企业重金招聘Python工程师标准>>> [数据结构和算法05] 红-黑树(看完包懂~) 置顶 2016年04月13日 15:50:25 eson_15 阅读数:526 ...

  6. 《恋上数据结构第1季》红黑树(未完)

    红黑树(Red Black Tree) 红黑树介绍 红黑树 与 4阶B树 红黑树 与 2-3-4树 等价转换 红黑树基础代码 完整的红黑树系列代码(恐怖如斯) 二叉树 BinaryTree.java ...

  7. 左倾红黑树Go语言实现

    文章目录 左倾红黑树的定义 红黑树性质 Node数据结构 旋转 插入 颜色转换 删除 实现 Keys Contains DeleteMin.DeleteMax Rank.Get Ceil Floor ...

  8. 左倾红黑树的go语言实现

    简介 红黑树经常能在计算机底层代码中见到,比如 C++的map,multimap, set, multiset Linux中rdtree用以管理内存和进程 Java中的HashMap 左倾红黑树是对红 ...

  9. 从2-3树谈到左倾红黑树

    2-3树 定义 顾名思义,2-3树,就是有2个儿子或3个儿子的节点.2-3树就是由这些节点构成.所以2-3-4树的每个节点都是下面中的一个: 空节点:空节点. 2-节点:包含一个元素和两个儿子. 3- ...

最新文章

  1. 以前写的一点东西,放上来吧。否则就扔掉了
  2. Android 内存优化
  3. android:imeOptions属性
  4. B 站 CEO 的身份证被上传到 GitHub 了?
  5. 36岁 计算机博士,36岁考博士
  6. 写小说的人是不是都很聪明呢?
  7. java包装_Java罐密封包装
  8. Dataguard之redo传输服务
  9. HighNewTech:新物种?这是一种不需要写代码的程序猿,这事,得从Ta们掌握了 iVX工具(首个无代码编程语言)说起……
  10. 快速实现对接京东EDI系统
  11. MYSQL 下载安装教程
  12. (新手必备)电子电路里面你必须知道的知识!!!
  13. x,y,w,h与xmin,ymin,xmax,ymax的关系
  14. 各种手机处理器排行榜_手机处理器性能排行榜和代表机型介绍
  15. 蒟蒻的WA之路——二分法学习
  16. 用Python分析了7w+《悬崖之上》影评,看看观众都是怎么说?
  17. 【转】怎样评价寒武纪的芯片1P 1M和MLU100?能够叫板英伟达吗?
  18. sai笔记7-制作笔刷
  19. 快速以太网中传输介质100BASE-TX
  20. HTML简单的图片瀑布流

热门文章

  1. HTTPS为啥子安全?
  2. 51单片机与AVR(SPI)单片机驱动DS1302
  3. maven打包可执行的jar包-包含依赖jar
  4. phpstudy打不开localhost
  5. 【数据结构】— 『队列』的实现以及LeetCode队列练习题
  6. Alternate Realities大赛作品引发的思考(二)——如何完全按照自己的思路制作一个toon shader
  7. 利用计算机设计轴对称图案,“轴对称图形”信息技术应用设计与分析|轴对称图形有哪些图片...
  8. Java 入门到精通的过程
  9. 文献解读|苍术属植物叶绿体基因组变异及系统发育关系
  10. openstack框架搭建云计算平台和各组件运维内容包括mysql、keyston、Glance、Nova、Neutron、Dashboard、Heat、Trove、Ceilometer运维