二叉树等总结

前言

在计算机科学中,良好的数据结构设计,能够让我们的算法更快更好。二叉树以及二叉树的一些变体(不知道这么说合适不)在很多算法中有很多实践。如Java8的HashMap用了红黑树等。本文简单介绍一下这些内容。

二叉树

二叉树(Binary Tree)是很多算法的基础数据结构,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。二叉树的第i层至多有2{i-1}个结点;深度为k的二叉树至多有2k-1个结点;对任何一棵二叉树T,如果其终端结点数为n_0,度为2的结点数为n_2,则n_0=n_2+1。
一棵深度为k,且有2k-1个节点的二叉树,称为满二叉树。这种树的特点是每一层上的节点数都是最大节点数。而在一棵二叉树中,除最后一层外,若其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,则此二叉树为完全二叉树。具有n个节点的完全二叉树的深度为log2n+1。深度为k的完全二叉树,至少有2(k-1)个节点,至多有2^k-1个节点。

二叉树的图如下所示:
二叉树

二叉查找树

二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。

二叉查找树就是对二叉树进行了一个排序。

二叉排序树在通常情况下可以达到O(logN)的静态、动态操作的时间复杂度。但是存在一种特殊情况,即输入的数据本身就是有序的,这时二叉排序树退化成向量。这种情况下,就需要平衡二叉树了。

平衡二叉树( AVL树)

平衡二叉树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,同时,平衡二叉树必定是二叉搜索树,反之则不一定。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

平衡二叉树通过旋转解决高度差的问题。树的旋转操作分为两种,左旋转和右旋转,这两种旋转是相对的。通过右旋或者左旋操作我们可以使一棵树继续保持平衡状态,并不会改变中序遍历的结果,但同时也要付出相应的代价。

AVL树旋转

红黑树

比较常见的平衡二叉树是红黑树。红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。

红黑树就是一颗满足一定条件的,相对平衡的二叉树,是二叉树和AVL树的一种折中。
红黑树的添加删除操作同二叉树一样,但是当添加删除等操作后使红黑树失去了他的特性后,就需要进行旋转操作来恢复红黑树的特性。
红黑树需要满足以下几点性质:

  1. 每个节点要么是红色,要么是黑色。
  2. 根节点永远是黑色的。
  3. 所有的叶节点都是空节点(即 null),并且是黑色的。
  4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的路径上不会有两个连续的红色节点)
  5. 从任一节点到其子树中每个叶子节点的路径都包含相同数量的黑色节点。(这就说明不能所有节点都是黑色)

从上面的性质 4 和 5来看,红色节点和黑色节点基本上是交替的出现,所以红黑树从根到叶子的最长的可能路径不多于最短的可能路径的两倍长,这样的结果是这个树大致上是平衡的。因为操作比如插入、删除和查找某个值的最坏情况时间都要求与树的高度成比例,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的。
下图是一颗标准的红黑树

红黑树并不是高度的平衡树。所谓平衡树指的是一棵空树或它的左右两个子树的高度差的绝对值不超过1。红黑树放弃了高度平衡的特性而只追求部分平衡,这种特性降低了插入、删除时对树旋转的要求,从而提升了树的整体性能。而其他平衡树比如AVL树虽然查找性能为性能是O(logn),但是为了维护其平衡特性,可能要在插入、删除操作时进行多次的旋转,产生比较大的消耗。

下面两张图是我从网上找的红黑树插入后调整的算法,不深入写了。

参考

Java集合(4)一 红黑树、TreeMap与TreeSet(下)
二叉搜索树
图解集合7:红黑树概念、红黑树的插入及旋转操作详细解读
图解集合 8 : 红黑树的移除节点操作

posted @ 2018-03-01 16:16  wardensky  阅读(433)  评论(0编辑  收藏  举报