[DataStructure] 说点不一样的树

扁担宽 板凳长
扁担想绑在板凳上
板凳不让扁担绑在板凳上
扁担偏要绑在板凳上
板凳偏偏不让扁担绑在那板凳上
到底扁担宽 还是板凳长
……

BST矮 BST高
BST有AVL 也有RBTree
各种形状的小树,各种性格的大树
到底小树好 还是大树好
……

暂时编到这里……
不知道为什么,各种树在大脑里各种浮现,想起了上面的歌词。
世间物种亿万万,人都个性习惯差异万万千,何况DataStructure世界里的这些树呢?

写在前面

“道生一,一生二,二生三,三生万物。”

任何事物都不是凭空产生,也不会兀自消失。
它们的出现都有各自的道理,生存也遵循着一定的法则,消失也有各自的缘由。
天空之浩瀚,江海之辽阔,处于其中的世间万物都在用自己的方式达到各自的平衡。

DataStructure里的各种树看得有点玄之又玄,如果只是记一些算法觉得并不能完全代表这些树结构存在的意义。
想写一些对这些树结构的理解和感受,而不是简单地重复概念,先不涉及算法代码相关,只是偶尔有了一些体会,想到哪写到哪吧。

如能让你产生一点共鸣,甚好;如不能,就当作者在自言自语。

关于树

大自然的树种有万千种,各有各的模样和特性,为了生存,各显神通。二进制世界里的“树”也是对大自然的一种映射吧。

事物并不是非黑即白。
树形结构的出现,是由链表进化而来,是从线性到非线性结构的发展。
而链表,又何尝不是一种特殊形状的树呢?

看过了好多篇关于树的技术文章,特别是红黑树的,一上来甩出来五条性质,balabala

《[DataStructure] 说点不一样的树》 RBTree性质.png

各种概念,各种图,如何出现,如何变色,又如何旋转,让人看得也天旋地转,看完还一头雾水。

忽然有一天觉得,红黑树,是道法自然的一种体现。
红与黑,不在意颜色,亦可看成黑白两道。

它的定义:一种自平衡二叉查找树。
自平衡,如何自平衡?平衡自在内心。

事物的出现自有它的道理,那么红黑树是怎样出现的?
它出现过程大致是:

二叉树 -> 二叉查找树(BST) -> AVL树
……. ……. …… …. …. ….. |
(B树 -> 2-3树)-> 红黑树(RB Tree)

BST

Binary Search Tree

BST先不说来龙去脉了,二叉查找树的出现自然是为了查找方便了。
如下,就是一棵BST了。

《[DataStructure] 说点不一样的树》 BST.png

但是BST在增删改查的过程中,也可能变成下面这样:

《[DataStructure] 说点不一样的树》 最坏运行情况O(N).png

它也符合BST的性质,但是看起来就极不平衡,一碰就倒,概况为“失衡”。

AVL

Self-Balancing Binary Search Tree / Height-Balanced Binary Search Tree
AVL树是最先发明的自平衡二叉搜索树(BBST)

从定义名字可以看出来,AVL是为了平衡而来。

“AVL”名字来源:其发明者前苏联学者 G.M. Adelson-Velsky 和 E.M. Landis 名字而命名。

英文定义如下:

Definition:
A tree is perfectly balanced if it is empty or the number of nodes in each subtree differ by no more than 1.

好一个“perfectly”~ But who is perfect?

它是一种高度平衡树,也是一种二叉搜索树,它的出现是为了解决二叉搜索树退化成链表的问题。

来个图看看,符合的性质:

  • 每棵子树中的左子树和右子树的深度差不能超过 1;
  • 二叉树中每棵子树都要求是平衡二叉树。

《[DataStructure] 说点不一样的树》 AVL Tree.png

AVL追求极致的平衡,而极致,也会带来弊端。
要追求什么,必然要通过另一些什么来换取。
而时刻要保持的“极致”,必然时刻要不松懈地维护。这其实挺累的。
它只是想要追求平衡的完美吧。

像红楼梦里的宝钗,贾府上上下下都对她赞不绝口,上至贾母王夫人,下至丫头,都喜欢她,为人周到,句句斟酌,让人舒服,大事化小,小事化了。厉害吗?当然很厉害。可是很累。

事事无绝对。
追求极致,就可能出现弊端。或者说,极致点,也是一个弱点。
世间就是这样。

  • 优点:
    查找元素时,速度很快。
  • 缺点:
    在添加或删除元素时,由于“追求极致的平衡”,通过不断地循环来达到自平衡,因而增加了时间复杂度。

AVL旋转

AVL左旋

《[DataStructure] 说点不一样的树》 AVL左旋.png

2-3树

在说红黑树之前,应该看一下2-3树,其实可以更好地认识红黑树。
(待补充)

红黑树(RB Tree)

既生瑜,何生亮?

还是来看看英文的定义~ 有时候英文的更好理解。

Definition:
Red-Black Trees are binary search trees that are named after the way the nodes are coloured.

Red-Black Tree is a self-balancing Binary Search Tree (BST) where every node follows following rules.

《[DataStructure] 说点不一样的树》
RedBlackTree

  1. **Every node has a color either red or black.
  2. **Root of tree is always black.
  3. **There are no two adjacent red nodes (A red node cannot have a red parent or red child).
  4. **Every path from a node (including root) to any of its descendant NULL node has the same number of black nodes.

看这个结构图和几条balabala的性质,是不是觉得很晕?很晕就对了~

先来了解个大概~
RB Tree也是平衡二叉搜索树,和AVL一样,都是Self-Balanced。
AVL追求极致的平衡,而红黑树的出现,大概就是为了弥补追求极致所造成的失衡,它只做到部分的平衡,是一种折中的表现。
RB Tree放弃的部分平衡,是为了换取增删操作时的效率。

牺牲了高度的绝对平衡,换来时间的优化。这比交换值不值?
我说值得你同意吗?

能力守恒,价值也是。
不同人的价值观不一样,但是你自己心里的天平会平衡就可以。旁人多说无益。

就像AVL树,为了平衡会要经过好多次旋转,旋转旋转……
白雪,夏夜,我不停歇……

而RB Tree的结构设计,使得任何不平衡都会在三次旋转之内解决。(很厉害!)

有得有失~ 有失有得~
得失,也是一种自平衡。

(它们如何旋转变化待补充~)

RB Tree的旋转

还是动图好看呀~

左旋

将E的右子树S绕E逆时针旋转,使得E的右子树S成为E的父亲,同时修改相关节点的引用。
旋转之后,二叉查找树的属性仍然满足。

《[DataStructure] 说点不一样的树》 左旋.gif

/** From CLR */
    private void rotateLeft(TreeMapEntry<K,V> p) {
        if (p != null) {
            TreeMapEntry<K,V> r = p.right;
            p.right = r.left;
            if (r.left != null)
                r.left.parent = p;
            r.parent = p.parent;
            if (p.parent == null)
                root = r;
            else if (p.parent.left == p)
                p.parent.left = r;
            else
                p.parent.right = r;
            r.left = p;
            p.parent = r;
        }
    }

右旋

将S的左子树绕S顺时针旋转,使得S的左子树成为S的父亲,同时修改相关节点的引用。
旋转之后,二叉查找树的属性仍然满足。

《[DataStructure] 说点不一样的树》 右旋.gif

/** From CLR */
    private void rotateRight(TreeMapEntry<K,V> p) {
        if (p != null) {
            TreeMapEntry<K,V> l = p.left;
            p.left = l.right;
            if (l.right != null) l.right.parent = p;
            l.parent = p.parent;
            if (p.parent == null)
                root = l;
            else if (p.parent.right == p)
                p.parent.right = l;
            else p.parent.left = l;
            l.right = p;
            p.parent = l;
        }
    }

AVL树和RB Tree对比

就AVL和RB Tree两种结构相比较,
AVL像一位特长生,显著的特长就是它的“绝对平衡”,锋芒毕露。
RB Tree像一位比较全面发展的学生,没有绝对的特长,但各方面表现都比较好,深谙折中之道。
不能说谁一定优于谁,“绝对”与“非绝对”也是相对,它们各自有自己的平衡,并且有自己的擅长点。

《[DataStructure] 说点不一样的树》 BST树的比较.png

写在后面

内容尚需修改与完善,如有表述不准确之处,望不吝指出,谢谢~

参考

    原文作者:blueMononoke
    原文地址: https://www.jianshu.com/p/9290529e3725
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞