在一颗二叉树中寻找一个结点的后继结点(前驱结点)
- 找后继结点
- 找前驱结点
找后继结点
首先知道什么是后继结点,就是二叉树中序遍历的序列中,某个结点紧随的那个结点比如下面的二叉树以及对应的中序遍历顺序。
则4
的后继是2
,2
的后继是5
,7
的后继是null
。
在树的结构中,每个结点有一个指向父亲的域parent
,看如下结构
1 | static class Node{ |
那么如何快速的寻找当前结点node
后继结点呢? 其实只需要分为两种情况
- 第一,如果
node
结点有右子树,那么就是右子树上最左的结点,例如上图的2
的右子树上的最左结点是5
,5
的右子树上最左的结点是8
,1
的右子树上最左的结点是9
,3
的右子树上最左的结点是7
。 - 第二,如果
node
结点没有右子树,那么要分两种情况 : a. 看当前结点node
是不是它父亲(node.parent)的左孩子,如果是,那么它父亲(node.parent
)就是它的后继;b.如果当前结点是它父亲的右孩子(node.parent.right == node
),那么就向上不停的寻找它的后继结点,即当前结点为node
,它的父亲为parent,如果node
还是parent
的右孩子,就令node= parent,parent = parent.parent
,一直向上,直到parent.left = node
,就停止,此时parent
就是当初要找的结点的后继。
(1) 对于上面的第二种情况看上面的例子,首先a
情况
(2) 然后再看第二种情况的b
,也就是往上找后继的过程
找前驱结点
这个和找后继是同理的:
- 当一个结点有左子树的时候,就是最左子树的最右结点;
- 没有左子树的时候,a. 看当前结点
node
是不是它父亲(node.parent
)的右孩子,如果是,那么它父亲(node.parent
)就是它的前驱;b. 如果当前结点是它父亲的左孩子(node.parent.left == node
),那么就向上不停的寻找它的前驱结点,即当前结点为node
,它的父亲为parent
,如果node
还是parent
的左孩子,就令node= parent,parent = parent.parent
,一直向上,直到parent.right = node
,就停止,此时parent
就是当初要找的结点的前驱。
完整的测试代码如下
1 | /** |
运行结果