二叉搜索树—平衡二叉树

  1. 二叉搜索树的基本概念

一棵二叉搜索树是以一棵二叉树来组织的,如下图所示,这样一棵可以使用一个链表数据结构来表示,其中每个结点就是一个对象。key、left、right、p分别指向结点的键值、左孩子、右孩子和双亲。如果某个孩子节点或者父节点不存在,则相应属性值为NIL。根节点是树中唯一父指针为NIL的节点。

《二叉搜索树—平衡二叉树》

(1)遍历关键字
通过递归算法来按序输出二叉树中的所有关键字,这种算法称为中序遍历(inorder tree walk)算法。调用如下代码输出T中的所有元素:

INORDER-TREE-WALK(x):
1.if x /=(不等于) NIL
2.	INORDER-TREE-WALK(x.left)
3.	print x.key
4.	INORDER-TREE-WALK(x.right)

上图输出为:1,3,4,6,7,8,10,13,14

遍历一棵有n个结点的二叉搜索树需要耗费 《二叉搜索树—平衡二叉树》(n) 时间。

(2)查找关键字:

TREE-SEARCH(x,k)
1.if x==NIL or k==x.key
2.	return x
3.if k<x.key
	return TREE-SEARCH(x.left,k)
4.else return TREE-SEARCH(x.right,k)

(3)最大关键字元素和最小关键字元素

TREE-MINMUM(x)  //最小关键字元素
1.while x.left/= NIL
2.	x=x.left
3.return x

TREE-MAXMUM(x)  //最大关键字元素
1.while x.left/= NIL
2.	x=x.left
3.return x

(4)后继和前驱

给定一个二叉搜索树中的一个结点,有时候需要按中序遍历的次序查找它的后继。如果所有的关键字互不相同,则一个结点x的后继是大于x.key 的最小关键字的结点。**一棵二叉树搜索树的结构允许我们通过没有任何关键字的比较来确定一个结点的后继。**如果后继存在,下面的过程将返回一棵二叉搜索树的结点的后继,否则返回NIL。

TREE-SUCCESSOR(x)
1.if x.right /= NIL
2.	return TREE-MINIMUM(x.right)
3.y=x.p   //3-7是为了找出7的后继,因为这时候7是没有右孩子的
4.while y /= NIL and x==y.right
5.      x=y
6.      y=y.p
7.return y

如上图所示,10是8的后继,这体现了1-2的代码行。8是7的后继,这体现了3-7的代码行。

在一棵高度为h的二叉搜索树中,动态集合上的SEARCH、MINIMUN、MAXIMUM、SUCCESSOR和PREDECESSOR 可以在O(h) 时间内完成。

(5)插入和删除
要将一个新值插入到一棵二叉树中,调用TREE-INSERT,以z作为输入,其中z.key=v,z.left=NIL,z.right=NIL为截止条件。

TREE-INSERT(T,z)
1.y=NIL
2.x=T.root
3.while x /= NIL
4.	y=x
5.	if z.key<x.key
6.	   x=x.left
7.	else x=x.right
8.z.p=y  //先寻找到最下面一个,然后使得y为z的双亲
9.if y==NIL
10.  T.root=z
11.elseif z.key<y.key  
12.  y.left=z
13.else y.right=z

TREE-INSERT 在一棵高度为h的树上的运行时间为O(h)

删除一个结点z的整个策略分为三种基本情况:
a.如果z没有孩子结点,那么只是简单的将他删除,并修改其父结点,用NIL作为孩子来替换z
b.如果z只有一个孩子,那么将这个孩子提升到树中z的位置上,并修改z的父节点,用z的孩子来替换z
c.如果z有俩个孩子,那么找z的后继y,并让y占据树中z的位置。z的原来右子树部分成为y的新的右子树,并且z的左子树称为y的新的左子树。

《二叉搜索树—平衡二叉树》

2.平衡二叉树

在上面的二叉树中,将一个数组{1,2,3,4}插入树的时候,形成了图1情况,对于以下情况,有建立树和没建立树对于数据的增删查改已经没有了任何帮助,反而增添维护成本,只有建立图2所示的二叉树才能真正体现出二叉树的优点。
《二叉搜索树—平衡二叉树》

平衡树有以下定义:
1.可以是空树。
2.假如不是空树,任何一个结点的左子树和右子树都是平衡二叉树,并且高度之差的绝对值不超过1

平衡因子: 左子树的高度减去右子树的高度。由平衡二叉树的定义可知,平衡因子的取值只可能是0,1,-1.分别对应着左右子树等高,左子树比较高,右子树比较高。如下图所示:

《二叉搜索树—平衡二叉树》

AVL树的删除时的失衡与调整:

(1) 树的删除
假如有一棵查找树如下,对树进行中序遍历,可以得到1,2,2.5,3。我们发现,这是一个递增序列。假如要删除的结点为3,那我们需要删除的结点为3,在考虑树的平衡问题时,用3的前驱来代替3。在2.5代替3之后,还不是平衡树。假如我们要删除的结点为2,在不考虑平衡的条件下,如下所示:

《二叉搜索树—平衡二叉树》

调整不平衡树后,导致了更大的不平衡树:

假设我们删除了结点6,那么最小不平衡树就是1,3,5了,它的双亲10的平衡因子为RH。我们首先对最小不平衡子树进行调整,结果如右图所示,我们发现,最小不平衡子树从根节点的做字数变成了整棵树,所以需要进一步进行调整:

《二叉搜索树—平衡二叉树》

插入时,进行一次平衡处理,整棵树就会处于平衡状态,而在删除时,需要进行多次平衡处理,才能保证树处于平衡状态。

LE与RE型的失衡树,在进行调整的时候,和LL与RR型的旋转方式是一致的。只是最后初始根结点的平衡因子不为EH而已。就拿上面的例子而言,调整后的结果如下。初始根结点的平衡因子为RH。相对应的,假如是LE的情况,调整后初始根结点的平衡因子为LH。
《二叉搜索树—平衡二叉树》

参考:http://www.cnblogs.com/suimeng/p/4560056.html(AVL)

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/Hansry/article/details/78207102
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞