前面介绍的算法在最坏的情况下还是很糟糕。这次会介绍一种二分查找树并能保证无论如何构造它,他的运行时间都是对数级别的。理想情况下我们希望能够保持二分查找树的平衡性。但是,在动态插入中保证树的完美平衡的代价太高了。

2-3查找树

我们将一棵标准的二叉查找树中的节点成为2-节点(含有一个键和两条链接),现在我们引入3-节点,它含有两个键和三条链接。
查找算法之平衡查找树

查找

要判断一个键是否在树中,我们先将它和根节点中的键比较。如果它和其中任意一个相等,查找命中;否则我们就根据比较的结果找到指向相应区间的链接,并在其指向的子树中递归的递归查找。如果这个是空链接,查找未命中。
查找算法之平衡查找树

插入

树的平衡:
任何节点的左子树和右子树之间的高度差不能超过1。

查找算法之平衡查找树

上图中(a)是平衡的,(b)是不平衡的,很显然,一个完全不平衡的树,在做查找时,它就是线性级别的性能,而平衡的二叉树,同样的数据量,但有效利用了平衡性,它的查找性能则能降到对数级别。

而动态平衡要求的是要在插入是,时刻保持树的平衡性。

分为几种情况:

向2-节点中插入新键

查找算法之平衡查找树

若未命中的查找结束于一个2-节点,我们只要把这个2节点替换为一个3节点就可以了。

向一棵只有3-节点的树中插入新键

查找算法之平衡查找树

为了新键的插入,首先临时将新键存入该节点中,使之成为一个4-节点。然后很容易就将他转化为一棵由3个2-节点组成的2-3树。

向一棵父节点为2-节点的3-节点中插入新键

查找算法之平衡查找树

假设未命中的查找结束于3-节点,而他的父节点是2-节点。我们先像刚才一样构造一个临时的4-节点并将其分解,但此时我们不会为中键创造一个新的节点,而是将其移动至原来的父节点中。

向一棵父节点为3-节点的3-节点中插入新键

查找算法之平衡查找树

假设未命中的查找结束于一个父节点为3-节点的节点,我们再次和刚才一样构造一个临时的4-节点并分解它,然后将他的中键插入它的父节点中,但父节点也是一个3-节点,因此我们再用这个中键构造一个临时的4-节点,然后在这个节点上进行相同的变换,就这样一直向上不断分解临时4-节点并将中键插入到更高层的父节点。

分解根节点

查找算法之平衡查找树

构造二叉树

查找算法之平衡查找树

总结

尽管我们可以用不同的数据类型表示2-节点和3-节点,但是这种直白的表示方法实现大多数操作并不方便,因为需要处理的情况太多。我们需要维护两种不同类型的节点,将被查找的键和节点中的每个键进行比较,将链接和其他信息从一种节点复制到另一种节点,将节点从一种数据类型转换到另一种类型,等等。不仅需要大量的代码,而且产生的额外开销可能会使算法比标准二叉树更慢。

相关文章:

  • 2022-12-23
  • 2021-06-25
  • 2022-01-01
  • 2021-09-09
  • 2021-05-26
  • 2021-12-27
  • 2021-12-08
猜你喜欢
  • 2021-11-05
  • 2021-12-01
  • 2021-10-03
  • 2021-07-18
相关资源
相似解决方案