扁担宽 板凳长扁担想绑在板凳上板凳不让扁担绑在板凳上扁担偏要绑在板凳上板凳偏偏不让扁担绑在那板凳上到底扁担宽 还是板凳长……BST矮 BST高BST有AVL 也有RBTree各种形状的小树,各种性格的大树到底小树好 还是大树好……复制代码
暂时编到这里……
不知道为什么,各种树在大脑里各种浮现,想起了上面的歌词。 世间物种亿万万,人都个性习惯差异万万千,何况DataStructure世界里的这些树呢?
写在前面
道生一,一生二,二生三,三生万物。复制代码
任何事物都不是凭空产生,也不会兀自消失。 它们的出现都有各自的道理,生存也遵循着一定的法则,消失也有各自的缘由。 天空之浩瀚,江海之辽阔,处于其中的世间万物都在用自己的方式达到各自的平衡。
DataStructure里的各种树看得有点玄之又玄,如果只是记一些算法觉得并不能完全代表这些树结构存在的意义。 想写一些对这些树结构的理解和感受,而不是简单地重复概念,先不涉及算法代码相关,只是偶尔有了一些体会,想到哪写到哪吧。
如能让你产生一点共鸣,甚好;如不能,就当作者在自言自语。
关于树
大自然的树种有万千种,各有各的模样和特性,为了生存,各显神通。二进制世界里的“树”也是对大自然的一种映射吧。
事物并不是非黑即白。 树形结构的出现,是由链表进化而来,是从线性到非线性结构的发展。 而链表,又何尝不是一种特殊形状的树呢?
看过了好多篇关于树的技术文章,特别是红黑树的,一上来甩出来五条性质,balabala
性质:1、节点是红色或黑色。2、根节点是黑色。3、所有叶子都是黑色(叶子是NIL节点)。4、每个红色节点必须有两个黑色的子节点。(从每个叶子到根的所有路径上不能有两个连续的红色节点。)5、从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点。复制代码
@_@
各种文字的概念,各种形状的树
如何出现,如何变色,又如何旋转,让人看得也天旋地转,看完还一头雾水啊~~~~~
忽然觉得,红黑树,是道法自然的一种体现。
红与黑,不在意颜色,亦可看成黑白两道。
它的定义:一种自平衡二叉查找树。 自平衡,如何自平衡?平衡自在内心。
事物的出现自有它的道理,那么红黑树是怎样出现的? 它出现过程大致是:
二叉树 -> 二叉查找树(BST) -> AVL树....... ....... ...... .... .... ..... | (B树 -> 2-3树)-> 红黑树(RB Tree)复制代码
BST
Binary Search Tree BST先不说来龙去脉了,看名字,二叉查找树的出现自然是为了查找方便了。 如下,就是一棵BST了。
但是BST在增删改查的过程中,也可能变成下面这样:
不想要这样的情况是不是?这是最坏的运行情况O(N)了,没有比这样更坏了。
但它也符合BST的性质,只是看起来就极不平衡,一碰就倒啦,极易失衡呢。
AVL
Self-Balancing Binary Search Tree / Height-Balanced Binary Search Tree复制代码
关于名字
名字不好懂?本来就不好懂~
"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?
好了好了,好好说~
AVL树是最先发明的自平衡二叉搜索树(BBST)
从定义名字可以看出来,AVL是为了平衡而来。
它是一种高度平衡树,也是一种二叉搜索树,它的出现是为了解决二叉搜索树退化成链表的问题。
性质有:
- 每棵子树中的左子树和右子树的深度差不能超过 1;
- 二叉树中每棵子树都要求是平衡二叉树。
来个图看看:
追求极致的平衡,而极致,也会带来弊端。要追求什么,必然要通过另一些什么来换取。而时刻要保持的“极致”,必然时刻要不松懈地维护。这其实挺累的。它只是想要追求平衡的完美吧。像红楼梦里的宝钗,贾府上上下下都对她赞不绝口,上至贾母王夫人,下至丫头,都喜欢她,为人周到,句句斟酌,让人舒服,大事化小,小事化了。厉害吗?当然很厉害。可是很累。事事无绝对。追求极致,就可能出现弊端。或者说,极致点,也是一个弱点。复制代码
优缺点
- 优点: 查找元素时,速度很快。
- 缺点: 在添加或删除元素时,由于“追求极致的平衡”,通过不断地循环来达到自平衡,因而增加了时间复杂度。
AVL旋转
AVL左旋
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.它是一棵自平衡二叉搜索树,遵循以下性质。RedBlackTree**Every node has a color either red or black.**Root of tree is always black.**There are no two adjacent red nodes (A red node cannot have a red parent or red child).**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只做到部分的平衡,是一种折中的表现。 它放弃的部分平衡,是为了换取增删操作时的效率。
牺牲了高度的绝对平衡,换来时间的优化。这比交换值不值? 我说值得你同意吗?
能力守恒,价值也是。 不同人的价值观不一样,但是你自己心里的天平会平衡就可以。旁人多说无益。
AVL树,为了平衡会要经过好多次旋转,旋转旋转……
白雪,夏夜,我不停歇……复制代码
而RB Tree的结构设计,使得任何不平衡都会在三次旋转之内解决。(很厉害!)
有得有失~ 有失有得~ 得失,也是一种自平衡。
(它们如何旋转变化待补充~)
RB Tree的旋转
左旋
- 将E的右子树S绕E逆时针旋转,使得E的右子树S成为E的父亲,同时修改相关节点的引用。
- 旋转之后,二叉查找树的属性仍然满足。
/** From CLR */ private void rotateLeft(TreeMapEntryp) { if (p != null) { TreeMapEntry 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的父亲,同时修改相关节点的引用。 旋转之后,二叉查找树的属性仍然满足。
(图片来源于资料文章)
/** From CLR */ private void rotateRight(TreeMapEntryp) { if (p != null) { TreeMapEntry 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 VS RB Tree
就AVL和RB Tree两种结构相比较,
- AVL像一位特长生,显著的特长就是它的“绝对平衡”,锋芒毕露。
- RB Tree像一位比较全面发展的学生,没有绝对的特长,但各方面表现都比较好,深谙折中之道。
不能说谁一定优于谁,“绝对”与“非绝对”也是相对(太绕),它们各自有自己的平衡,并且有自己的擅长点。
写在后面
内容尚需补充与完善,偶有写着写着内容飘向别处,随便看看就好~