不带parent指针的successor求解

Posted xiaoyh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不带parent指针的successor求解相关的知识,希望对你有一定的参考价值。

问题:

  请设计一个算法,寻找二叉树中指定结点的下一个结点(即中序遍历的后继)。给定树的根结点指针TreeNode* root和结点的值int p,请返回值为p的结点的后继结点的值。保证结点的值大于等于零小于等于100000且没有重复值,若不存在后继返回-1。注意这里没有parent指针。

思路:

  本质上还是二叉树的中序遍历。所以经过前面的学习我们有递归和非递归两种解法。

  解法一(递归解法):

技术图片
 1 public class Successor2 {
 2     public int findSucc(TreeNode root, int p) {
 3         if (root == null)
 4             return -1;
 5         in(root, p);
 6         return succ;
 7     }
 8 
 9     private void in(TreeNode<Integer> node, int p) {
10         if (node == null)
11             return;
12         in(node.left, p);
13         if (preValue == p) {
14             if (succ != -1)
15                 return;
16             succ = node.val;
17             // System.out.println(succ);
18             return;
19         }
20         preValue = node.val;
21         in(node.right, p);
22     }
23 
24     private int preValue = Integer.MIN_VALUE;
25     private int succ = -1;
26 
27     public static void main(String[] args) {
28         TreeNode root = buildTree(8, 6, 10);
29         root.left.left = buildTree(3, 1, 4);
30         root.right.right = buildTree(13, 11, 15);
31         root.right.left = new TreeNode(9);
32 
33         final Successor2 tool = new Successor2();
34         System.out.println(tool.findSucc(root, 8));  // 输出9
35     }
36 
37     public static <T> TreeNode<T> buildTree(T rootValue, T lValue, T rValue) {
38         TreeNode root = new TreeNode(rootValue);
39         TreeNode left = new TreeNode(lValue);
40         TreeNode right = new TreeNode(rValue);
41         root.left = left;
42         root.right = right;
43         return root;
44     }
45 
46     public static class TreeNode<T> {
47 
48         public T val;
49         public TreeNode<T> left = null;
50         public TreeNode<T> right = null;
51 
52         public TreeNode(T val) {
53             this.val = val;
54         }
55 
56     }
57 }
View Code

  解法二(非递归解法):

技术图片
 1 import java.util.Stack;
 2 
 3 public class Successor1 {
 4     public int findSucc(TreeNode<Integer> root, int p) {
 5         if (root == null)
 6             return -1;
 7         Stack<TreeNode> stack = new Stack<TreeNode>();
 8         TreeNode curr = root;
 9         boolean isFound = false;
10         // curr不为空或者栈不为空,都可以继续处理
11         while (curr != null || !stack.isEmpty()) {// 没有生产也没有消费,就退出循环了
12             // 左支路依次入栈
13             while (curr != null) {
14                 stack.add(curr);
15                 curr = curr.left;
16             }
17             if (!stack.isEmpty()) {
18                 TreeNode<Integer> pop = stack.pop();// 栈的弹出顺序就是中序遍历的顺序
19                 // 上一轮修改了标志位,当前出栈的值就是我们需要的值
20                 if (isFound) {
21                     return pop.val;
22                 }
23                 // 如果弹出值和p相同,那么下次弹出的值就是我们需要的值,修改标志位
24                 else if (pop.val == p) {
25                     isFound = true;
26                 }
27                 // curr指向pop的右子树,继续外层循环
28                 curr = pop.right;// 有可能为空,为空,只消费栈中内容,不为空,就要向栈中生产若干内容
29             }
30         }
31         return -1;
32     }
33 
34     public static void main(String[] args) {
35         TreeNode<Integer> root = buildTree(1, 2, 3);
36         root.left.left = buildTree(4, 5, 6);
37         root.right.right = buildTree(7, 8, 9);
38 
39         System.out.println(new Successor1().findSucc(root, 3));  // 输出8
40     }
41 
42     public static <T> TreeNode<T> buildTree(T rootValue, T lValue, T rValue) {
43         TreeNode root = new TreeNode(rootValue);
44         TreeNode left = new TreeNode(lValue);
45         TreeNode right = new TreeNode(rValue);
46         root.left = left;
47         root.right = right;
48         return root;
49     }
50 
51     public static class TreeNode<T> {
52 
53         public T val;
54         public TreeNode<T> left = null;
55         public TreeNode<T> right = null;
56 
57         public TreeNode(T val) {
58             this.val = val;
59         }
60 
61     }
62 }
View Code

 

以上是关于不带parent指针的successor求解的主要内容,如果未能解决你的问题,请参考以下文章

函数指针--菜鸟求解。

QT调试时怎么查看某个指针指向的一片内存区域的信息

JavaScript 中怎么不带括号的调用函数

Java 求解翻转链表

不带星号的函数指针参数

带/不带功能的指针