在学习红黑树的时候,看了不少文章,发现都没有讲明白红黑树的原理,只是简单列了红黑树的几条规则,就开始讲解红黑树的插入,让人一直不知其因此然。也很难深入的理解红黑树。
最后翻起了《算法》这本书,仔细了解了二叉树查找树、2-3树、红黑树,才明白了红黑树不是无缘无故产生的,而是符合科学的发展观念是按部就班,站在巨人的肩旁上发展起来的。html
这也是咱们从学生时代的填鸭式的学习方式的转变,不单单是只学习结论,而且要了解结论产生的历史及发展。
这样咱们才能从搬砖、码农成长为工程师、科学家。java
一位计算机科学的大牛说过:node
程序 = 数据结构 + 算法
数据结构是为了减小查询、删除的时间复杂度和空间复杂度。git
链表的一个节点是由:节点值、节点的下一个节点(字节点)的地址
二叉查找树一个节点:节点值、节点的左子节点的地址、节点的右子节点的地址
2-3树:由2节点、3节点组成github
![图. 2节点 3节点]()算法
2节点:微信
3节点:markdown
红黑树(平衡二叉查找树):节点值、节点的左子节点、节点的右子节点、节点颜色数据结构
二叉查找树:是由2节点的树组成的,最坏的时间复杂度是O(N)
插入的几种状况:学习
根据以上的四种状况,咱们能够看出,若是咱们插入的值是从1开始逐渐递增的,那么树就最终生长得很像链表。
private Node<T> root = null;//根节点 private class Node<T>{ public T value;//为了下面的简单演示设属性为 pubilc public Node<T> left;//真正使用的时候应该为private 用get、set方法访问 public Node<T> right; public Node<T> parent; public Node(T value, Node<T> parent) { this.value = value; this.parent = parent; } }
若是查找的值等于根节点的值,那么查找命中,不然递归的在根的子树中(经过比较与根节点的值选择左/右节点)查找。
//返回null 树中没有此节点 ,递归的下左/右子节点查询 public Node<T> get(T value){ Node<T> node = root; while(true){ if(node == null){ return null; } if(node.value == value){ return node; }else if(node.value > value){ if(node.right == null){ return null; }else if(node.right.value == value){ return node.right; } node = node.right; }else if(node.value < value){ if(node.left == null){ return null; }else if(node.left.value == value){ return node.left; } node = node.left; } } }
插入和查找很像,若是树的根节点为空(空树)则插入到根节点,不然递归的在子树中判断,当子树为null的时候,插入。
public Node<T> put(T value){ Node<T> node = root; while(true){ if(node == null){ Node<T> node1 = new Node<>(value,null); root = node1;//空树,插入的为根节点 return node1; } if(node.value == value){ return node; }else if(node.value > value){ if(node.right == null){ Node<T> node1 = new Node<>(value,node); node.right = node1; return node1; }else if(node.right.value == value){ return node.right; } node = node.right; }else if(node.value < value){ if(node.left == null){ Node<T> node1 = new Node<>(value,node); node.left = node1; return node1; }else if(node.left.value == value){ return node.left; } node = node.left; } } }
为了解决二叉查找树的不平衡,2-3树孕育而生,2-3树可以很好的实现树的平衡。
2-3树的节点再也不是单一的2节点,节点多是2节点、3节点。
2节点:有一个值,两个子节点
3节点:有两个值,三个子节点。
注意二叉查找树是向下生长,而2-3树是向上生长。
当2-3的根节点由3树生长为(红黑树中的旋转)2节点,树的高度增长。
2-3树的查找和二叉查找树的思路是相同的都是迭代的思想。不过不一样的是在判断节点是否相同时2-3树要判断是否相等于左值或右值,若是大于左值小于右值,则从中子节点开始递归。
2-3树的插入有如下几种状况:
插入的节点做为根节点而且为2节点。
插入的节点为2节点,2节点转化为3节点。
插入的节点为3节点,则临时调整3节点为4节点(三个值),4节点中的中值变为左右值的父。
则4节点,转化为3个2节点。
则4节点的中子转化为父节点的值,父节点转化为3节点。
则3节点的中子节点转为父节点的值,父节点临时转化为4节点,此时就变成了插入的节点为3节点的状况上面的两种状况。
经过对比,2-3和二叉树的上图的插入,能够看到2-3最终是会自平衡的,而二叉查找树最坏会变成链表的形式(长的像链表).
红黑树实际上是2-3树的一种只含2节点的表现形式。仍是二叉树节点大于左子节点,小于右子节点。
咱们把2-3树中的2节点用黑色表示,3节点用红色表示(3节点的左节点为黑色、右节点为红色)
将红色连接画平就是2-3树。
左旋、右旋其实就是2-3树的3节点临时变为4节点,4节点的分解。
把红黑树的插入当作是2-3树的插入,就能明白红黑树的节点插入,节点的旋转,及根据红黑树的
对比2-3的几种插入状况,就能理解红黑树的插入状况。
https://github.com/CarpenterL...
一个红黑树生成过程: https://www.cs.usfca.edu/~gal...
张无忌的回答:
https://www.zhihu.com/questio...
建议看一下《算法》第四版红皮书。
其实理解红黑树起来也不是那么困难。
<br/><br/>
关注个人公众号第一时间阅读有趣的技术故事
扫码关注:也能够在微信搜索公众号便可关注我:codexiulian 渴望与你一块儿成长进步!