二叉搜索树的前驱和后继详细推导
后继和前驱
定义:一个结点的后继,是大于x.key的最小关键字的结点。
一个结点的前驱,是小于x.key的最大关键字的结点。
思路:找一个结点的前驱或者后继,无非是在三个区域找。
首先分析前驱:
满足两个条件,一是要小于当前键值,那么只有LP和LS区可以找。
二要求是其中最大的值。我们知道,对于LP来说,X、LS、RS都属于他的右子树,那么,X、LS和RS都是大于它的。
所以很显然,前驱就是LS中的最大值,即前驱 = 左子树中的最大值。条件是:存在左子树。
那不存在左子树只有左父母的情况呢?
那只能在LP上找了,LP也具有两部分,第一部分是LP的LS,LP的LS虽然满足小于X的条件,但是LP的LS中所有元素都是小于LP的,所以至少也是LP。
还有一部分,LP可能有左父母或者右父母,显然,右父母大于他的所有左子树,包括X,条件一都不满足,显然不行。左父母小于LP,所以它竞争不过LP。
所以最终结论就是,在只有左父母,没有左子树的情况,前驱 = 左父母的值。
那不存在左子树和左父母的情况呢?
那就只剩下右子树和右父母了,显然,右子树肯定不行,它的所有元素都大于X。那就只能在右父母中找了,毕竟虽然右父母大于它,但是右父母也有左/右父母和右子树。
右父母的右父母,和右子树都不行,都大于右父母本身,更大于X了。那就只能在右父母的左父母上找了,对于左父母来说,他的右子树全都大于他,即包括X的右父母和X,所以,此时找到的左父母就是我们的前驱。
所以,不存在左子树和左父母的情况,前驱 = 右父母的左父母(如果右父母不存在左父母,就一直往上遍历,直至出现左父母)。
分析完毕。下面是代码实现。
因为我们的二叉树的结点只有Left和Right指针,所以这题感觉要用递归来做,或者栈。下面我们用栈写一个吧(时间复杂度是O(N))
- BinTree Predecessor(BinTree X,BinTree BST)
- {
- if(X->Left!=NULL)
- return FindMax(X->Left);
- else
- {
- Stack S;
- S = CreatStack();
- while(BST!=X)
- {
- Push(S,BST);
- if(X->Data > BST->Data)
- BST = BST->Right;
- else if(X->Data < BST->Data)
- BST = BST->Left;
- }
- BinTree Par,Son;
- Son = X;
- while((Par = Pop(S))->Right!=Son)Son = Par;//相当于Case2&3结合,直至找到左母亲为止。
- return Par;
- }
- }
插播一个递归和栈的区别:
接着分析后继:(类比前驱)
满足两个条件,一是要大于当前键值,那么只有RP和RS区可以找。
二要求是其中最小的值。我们知道,对于RP来说,X、LS、RS都属于他的左子树,那么,X、LS和RS都是小于它的。
所以很显然,前驱就是RS中的最小值,即后继 = 右子树中的最小值。条件是:存在右子树。
那不存在右子树只有右父母的情况呢?
那只能在RP上找了,RP也具有两部分,第一部分是LP的RS,RP的RS虽然满足大于X的条件,但是RP的RS中所有元素都是大于LP的,所以找后继,至少也得是RP。
还有一部分,RP可能有左父母或者右父母,显然,左父母小于他的所有右子树,包括X,条件一都不满足,显然不行。右父母大于RP,所以它竞争不过RP。
所以最终结论就是,在只有右父母,没有右子树的情况,后继 = 右父母的值。
那不存在右子树和右父母的情况呢?
那就只剩下左子树和左父母了,显然,左子树肯定不行,它的所有元素都小于X。那就只能在左父母中找了,毕竟虽然左父母小于它,但是右父母也有它本身的左/右父母和左子树。
左父母的左父母,和左子树都不行,都小于左父母本身,更小于X了。那就只能在左父母的右父母上找了,对于它的右父母来说,他的左子树全都小于他,即包括X的左父母和X,所以,此时找到的右父母就是我们的后继。
所以,不存在右子树和右父母的情况,后继 = 左父母的右父母(如果左父母不存在右父母,就一直往上遍历,直至出现右父母)。
分析完毕。下面是代码实现,同样是用栈实现。
- BinTree Successor(BinTree X,BinTree BST)
- {
- if(X->Right)
- return FindMin(X->Right);
- else
- {
- Stack S;
- S = CreatStack();
- while(BST!=X)
- {
- Push(S,BST);
- if(X->Data > BST->Data)
- BST = BST->Right;
- else if(X->Data < BST->Data)
- BST = BST->Left;
- }
- BinTree Par,Son;
- Son = X;
- while((Par = Pop(S))->Left!=Son )Son = Par;
- return Par;
- }
- }
基本上是一样的。