剑指offer面试题8:二叉树的下一个节点

题目:给定一颗二叉树和其中的一个节点,如何找出中序遍历序列的下一个节点?树中的节点除了有两个分别指向左、右子节点的指针,还有一个指向父节点的指针。

/**
 * @version 1.0
 * @Author zjay
 * @Date: 2021/8/18$
 * @Description: TODO
 * 题目:给定一颗二叉树和其中的一个节点,如何找出中序遍历序列的下一个节点?
 * 树中的节点除了有两个分别指向左、右子节点的指针,还有一个指向父节点的指针。
 * 思路分析:
 * 关键点1:中序遍历的下一个节点,因为是中序遍历,所以节点的左子树必为节点的上一个节点,不同考虑节点的左子树
 * 接下来分情况讨论:
 * 1.节点没有右子树:
 *      若为父节点的左子节点,则其下一个节点为父节点;
 *      若为父节点的右子节点,则下一个节点为该节点的父节点的父节点。。不为右子树的节点的父节点,比如 9的下一个节点是1,
 *      9为5的右子节点,5为2的右子节点,2不为1的右子节点,所以9的下一个为2的父子节点1.
 * 2. 节点有右子树
 *     下一个节点为右子树的最左节点。
 *
 */
public class Test8_BinaryTreeGetNext {
    public static void main(String[] args) {
        // 构建二叉树
        BinaryTreeNode node1 = new BinaryTreeNode(1);
        BinaryTreeNode node2 = new BinaryTreeNode(2);
        BinaryTreeNode node3 = new BinaryTreeNode(3);
        BinaryTreeNode node4 = new BinaryTreeNode(4);
        BinaryTreeNode node5 = new BinaryTreeNode(5);
        BinaryTreeNode node6 = new BinaryTreeNode(6);
        BinaryTreeNode node7 = new BinaryTreeNode(7);
        BinaryTreeNode node8 = new BinaryTreeNode(8);
        BinaryTreeNode node9 = new BinaryTreeNode(9);
        node1.left = node2;
        node1.right = node3;
        node1.parent = null;
        node2.left = node4;
        node2.right = node5;
        node2.parent = node1;
        node3.left = node6;
        node3.right = node7;
        node3.parent = node1;
        node4.parent = node2;
        node5.left = node8;
        node5.right = node9;
        node5.parent = node2;
        node6.parent = node3;
        node7.parent = node3;
        node8.parent = node5;
        node9.parent = node5;

        // 中序遍历结果
        //infixOrder(node1);

        //获取输入节点的下一个节点
        BinaryTreeNode nextNode = getNext(node1); // 有右子树节点测试
        BinaryTreeNode nextNode1 = getNext(node6); // 没有右子树节点测试,为父节点的左子节点
        BinaryTreeNode nextNode2 = getNext(node7); // 没有右子树节点测试,为父节点的右子节点
        if(nextNode2 != null) {
            System.out.println(nextNode2.val);
        } else {
            System.out.println("null");
        }
    }


    public static void infixOrder(BinaryTreeNode head){
        if(head.left != null) {
            infixOrder(head.left);
        }
        System.out.println(head.val);
        if(head.right != null) {
            infixOrder(head.right);
        }
    }

    /**
     * 寻找二叉树中指定节点的中序遍历下一个节点
     * @param node 输入指定的节点
     * @return 返回指定节点的下一个节点
     */
    public static BinaryTreeNode getNext(BinaryTreeNode node) {
        // 非法输入判断
        if(node == null) {
            return null;
        }

        BinaryTreeNode targetNode = null;


        if(node.right != null) { // 节点右子树不为空
            targetNode = node.right;
            while (targetNode.left != null) {
                targetNode = targetNode.left;
            }
        } else { // 节点没有右子树
            if(node.parent == null) { //该节点为根节点,且没有右子树,下一个为Null
                return null;
            }else {
                if (node.parent.left == node) { // 节点为父节点的左子节点
                    return node.parent;
                } else { // 节点为父节点的右子节点
                    targetNode = node;
                    //此处targetNode.parent != null放面前,不满足不用判断后面的条件
                    //若targetNode.parent此时为空,即7节点开始,null没有左子节点,会空指针异常
                    while (targetNode.parent != null && targetNode.parent.left != targetNode  ) {
                        targetNode = targetNode.parent;
                    }
                    if(targetNode.parent != null) { // 循环结束后,target为其父节点的左子节点
                        targetNode = targetNode.parent;
                    } else {
                        return null;
                    }
                }
            }
        }
        return targetNode;
    }
}

//二叉树节点类
class BinaryTreeNode{
    int val;
    BinaryTreeNode left;
    BinaryTreeNode right;
    BinaryTreeNode parent;

    public BinaryTreeNode(int val) {
        this.val = val;
    }
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值