1、题目
二叉树结构如下定义:
class TreeNode {
public:
V value;
TreeNode *left;
TreeNode *right;
TreeNode *parent;
};
给定二叉树中的某个节点,返回该节点的后继节点。
2、分析
后继节点:中序遍历序列中的当前节点的下一个节点。
经典做法:给定根节点,中序遍历生成一个序列,在这个序列中找到给定的节点的后一个节点,时间复杂度 O(N)O(N)O(N)。
但是通过二叉树结构,能知道当前节点的左孩子、右孩子及其父亲,那么存在一个 O(k)O(k)O(k) (其中 kkk 为 当前节点到后继节点的真实距离)时间复杂度的算法能找到给定节点的后继节点。
这就需要从结构上分析一个节点和其后继节点的关系。
分两种情况:
- 给定的 X 节点 有右树,因为后继节点是中序遍历序列中的 X 的下一个,那么毫无疑问,X 中序遍历序列的下一个一定是 X 右树上的最左孩子;
- 给定的 X 节点 无右树,X 不断往上找,找到某个节点是另一个节点的 P 的左孩子,那么 P 就是 X 的后继节点,本质就是在找 X 是哪个节点的左树上的最右节点。
3、实现
C++ 版
/*************************************************************************
> File Name: 032.返回给定节点的后继节点.cpp
> Author: Maureen
> Mail: Maureen@qq.com
> Created Time: 三 6/22 12:15:48 2022
************************************************************************/
#include <iostream>
using namespace std;
class TreeNode {
public:
int value;
TreeNode *left;
TreeNode *right;
TreeNode *parent;
TreeNode(int v) : value(v) {}
};
//找到右树的最左孩子
TreeNode *getLeftMost(TreeNode *node) {
if (node == nullptr)
return nullptr;
while (node->left != nullptr) {
node = node->left;
}
return node;
}
TreeNode *getSuccessorTreeNode(TreeNode *node) {
if (node == nullptr) return node;
if (node->right != nullptr) { //存在右树
return getLeftMost(node->right);
} else { //不存在右树
TreeNode *parent = node->parent;
//当前节点是其父节点的右孩子
while (parent != nullptr && parent->right == node) {
node = parent;
parent = node->parent;
}
return parent;
}
}
int main() {
TreeNode *root = new TreeNode(6);
root->parent = nullptr;
root->left = new TreeNode(3);
root->left->parent = root;
root->left->left = new TreeNode(1);
root->left->left->parent = root->left;
root->left->left->right = new TreeNode(2);
root->left->left->right->parent = root->left->left;
root->left->right = new TreeNode(4);
root->left->right->parent = root->left;
root->left->right->right = new TreeNode(5);
root->left->right->right->parent = root->left->right;
root->right = new TreeNode(9);
root->right->parent = root;
root->right->left = new TreeNode(8);
root->right->left->parent = root->right;
root->right->left->left = new TreeNode(7);
root->right->left->left->parent = root->right->left;
root->right->right = new TreeNode(10);
root->right->right->parent = root->right;
TreeNode *test = root->left->left;
cout << test->value << " next: " << getSuccessorTreeNode(test)->value << endl;
test = root->left->left->right;
cout << test->value << " next: " << getSuccessorTreeNode(test)->value << endl;
test = root->left;
cout << test->value << " next: " << getSuccessorTreeNode(test)->value << endl;
test = root->left->right;
cout << test->value << " next: " << getSuccessorTreeNode(test)->value << endl;
test = root->left->right->right;
cout << test->value << " next: " << getSuccessorTreeNode(test)->value << endl;
test = root;
cout << test->value << " next: " << getSuccessorTreeNode(test)->value << endl;
test = root->right->left->left;
cout << test->value << " next: " << getSuccessorTreeNode(test)->value << endl;
test = root->right->left;
cout << test->value << " next: " << getSuccessorTreeNode(test)->value << endl;
test = root->right;
cout << test->value << " next: " << getSuccessorTreeNode(test)->value << endl;
test = root->right->right; // 10's next is null
cout << test->value << " next: " << getSuccessorTreeNode(test) << endl;
return 0;
}
Java 版
public class SuccessorNode {
public static class Node {
public int value;
public Node left;
public Node right;
public Node parent;
public Node(int data) {
this.value = data;
}
}
public static Node getSuccessorNode(Node node) {
if (node == null) {
return node;
}
if (node.right != null) {
return getLeftMost(node.right);
} else { // 无右子树
Node parent = node.parent;
while (parent != null && parent.right == node) { // 当前节点是其父亲节点右孩子
node = parent;
parent = node.parent;
}
return parent;
}
}
public static Node getLeftMost(Node node) {
if (node == null) {
return node;
}
while (node.left != null) {
node = node.left;
}
return node;
}
public static void main(String[] args) {
Node head = new Node(6);
head.parent = null;
head.left = new Node(3);
head.left.parent = head;
head.left.left = new Node(1);
head.left.left.parent = head.left;
head.left.left.right = new Node(2);
head.left.left.right.parent = head.left.left;
head.left.right = new Node(4);
head.left.right.parent = head.left;
head.left.right.right = new Node(5);
head.left.right.right.parent = head.left.right;
head.right = new Node(9);
head.right.parent = head;
head.right.left = new Node(8);
head.right.left.parent = head.right;
head.right.left.left = new Node(7);
head.right.left.left.parent = head.right.left;
head.right.right = new Node(10);
head.right.right.parent = head.right;
Node test = head.left.left;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.left.left.right;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.left;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.left.right;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.left.right.right;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.right.left.left;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.right.left;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.right;
System.out.println(test.value + " next: " + getSuccessorNode(test).value);
test = head.right.right; // 10's next is null
System.out.println(test.value + " next: " + getSuccessorNode(test));
}
}