给定二叉树的某个节点,返回该节点的后继节点

这篇博客介绍了如何在二叉树中高效地找到给定节点的后继节点,通过分析节点与其后继节点的关系,提出两种情况:1) 当节点有右子树时,后继节点是其右子树中最左的孩子;2) 当节点无右子树时,需要向上找到某个节点成为其父节点的左孩子。提供了C++和Java两种语言的实现,实现了O(k)时间复杂度的查找算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 为 当前节点到后继节点的真实距离)时间复杂度的算法能找到给定节点的后继节点。

这就需要从结构上分析一个节点和其后继节点的关系。

分两种情况:

  1. 给定的 X 节点 有右树,因为后继节点是中序遍历序列中的 X 的下一个,那么毫无疑问,X 中序遍历序列的下一个一定是 X 右树上的最左孩子;
  2. 给定的 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));
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值