找到二叉树某节点按中序遍历顺序的下一个节点

280 阅读2分钟

问题

一个二叉树,其节点的结构是这样的

type TreeNode struct {
    Val interface{}
    Left *TreeNode // 左孩子
    Right *TreeNode // 右孩子
    Parent *TreeNode // 父节点
}

给你这个二叉树的任意一个节点,请找到该节点的按中序遍历顺序的下一个节点。也就是实现该函数

func GetNextNode(node *TreeNode) *TreeNode

注意:输入中并没有二叉树根节点。

分析

中序遍历过程中,二叉树的某个节点(设该节点为X)的下个节点,有这样几种情况

  • X有右子树,那么右子树的“最左最下”节点就是下一个节点。
  • X没有右子树,X是其父节点P的左孩子,那么P就是下一个节点。
  • X没有右子树,也不是其父节点的左孩子,此时就需要从X遍历其祖先节点,找到这样的一个祖先节点A——A是其父节点P的左孩子,则P就是下一个节点。

实现

在上述分析基础上,再简化,得到如下代码

func GetNextNode(node *TreeNode) *TreeNode {
    if node == nil {
        return nil
    }
    if node.Right != nil {
        return getLeftMost(node.Right)
    }
    curr := node
    for curr != nil && curr.Parent != nil {
        if curr == curr.Parent.Left {
            return curr.Parent
        }
        curr = curr.Parent
    }
    return nil
}

// 找到以root为根节点的某子树的最左最下节点
func getLeftMost(root *TreeNode) *TreeNode {
    curr := root
    for curr != nil && curr.Left != nil {
        curr = curr.Left
    }
    return curr
}

下面是测试代码

package main

import (
	"fmt"
)

func main() {
	{
		n1 := &TreeNode{Val: 1}
		n2 := &TreeNode{Val: 2}
		n1.Left = n2
		n2.Parent = n1
		n3 := &TreeNode{
			Val: 3,
		}
		n4 := &TreeNode{
			Val: 4,
			Parent: n3,
		}
		n3.Left = n4
		n2.Right = n3
		n3.Parent = n2
		// n2有右子树
		t.Log(GetNextNode(n2))
	}
	{
		n1 := &TreeNode{Val: 1}
		n2 := &TreeNode{Val: 2}
		n1.Left = n2
		n2.Parent = n1
                // n2没有右孩子。
                // 它是其父节点的左孩子。
		fmt.Println(GetNextNode(n2))
	}
	{
                // n1没有右孩子,也没有父节点。
		n1 := &TreeNode{Val: 1}
		fmt.Println(GetNextNode(n1))
	}
	{
		n1 := &TreeNode{Val: 1}
		n2 := &TreeNode{Val: 2}
		n1.Left = n2
		n2.Parent = n1
		n3 := &TreeNode{Val: 3}
		n2.Right = n3
		n3.Parent = n2
                // n3没有右孩子,
                // 它不是其父节点的左孩子。
		fmt.Println(GetNextNode(n3))
	}
}