数据结构——Java实现二叉树

相关概念

  存储结构:

  1. 顺序存储结构:二叉树的顺序存储结构适用于完全二叉树,对完全二叉树进行顺序编号,通过二叉树的性质五(第1个结点为根结点,第i个结点的左孩子为第2i个结点,右孩子为第2i+1个结点)。
  2. 链式存储结构:一般情况下,采用链式存储结构来存储二叉树。每个结点有3个域:data、left、right。

  遍历:

  1. 先根次序:根->左->右。
  2. 中根次序:左->根->右。
  3. 后根次序:左->右->根。

  遍历算法:

  1. 递归
  2. 非递归:通过设立一个栈。

声明二叉树结点类

 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年7月16日 上午8:19:15
 5  */
 6 package Two;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class TreeNode {
13     int val;
14     TreeNode left;
15     TreeNode right;
16     TreeNode(int x) {
17         val = x;
18     }
19     /**
20      * 先根遍历
21      * @param p
22      */
23     public void preorder(TreeNode p) {
24         if(p != null) {
25             System.out.print(p.val + " ");
26             preorder(p.left);
27             preorder(p.right);
28         }
29     }
30     /**
31      * 中根遍历
32      * @param p
33      */
34     public void inorder(TreeNode p) {
35         if(p != null) {
36             preorder(p.left);
37             System.out.print(p.val + " ");
38             preorder(p.right);
39         }
40     }
41     /**
42      * 后根遍历
43      * @param p
44      */
45     public void postorder(TreeNode p) {
46         if(p != null) {
47             preorder(p.left);
48             preorder(p.right);
49             System.out.print(p.val + " ");
50         }
51     }
52 }

声明二叉树类 和 由先根遍历与中根遍历构造二叉树

  建立一颗二叉树必须明确以下两点:

  1. 结点与双亲结点及孩子结点间的层次关系。
  2. 兄弟结点间的左右子树的顺序关系。

  先根次序或后根次序反映双亲与孩子结点的层次关系,中根次序反映兄弟结点间的左右次序。所以,已知先根和中根两种遍历序列,或中根和后根两种遍历序列才能够唯一确定一颗二叉树。而已知先根和后根两种遍历序列仍无法唯一确定一颗二叉树。

  1 /**
  2  * Copyright 2016 Zhengbin's Studio.
  3  * All right reserved.
  4  * 2016年7月16日 上午9:30:01
  5  */
  6 package Two;
  7 
  8 import java.util.Arrays;
  9 
 10 /**
 11  * @author zhengbinMac
 12  *
 13  */
 14 public class Tree {
 15     protected TreeNode root;
 16     public Tree() {
 17         root = null;
 18     }
 19     public Tree(int[] pre, int[] in) {
 20 //        root = reConstructBinaryTree(pre, in);
 21         root = reConstructBinaryTree1(pre, in);
 22     }
 23     /**
 24      * 先根次序
 25      */
 26     public void preorderTraversal() {
 27         System.out.println("先根次序遍历:");
 28         if(root != null) {
 29             root.preorder(root);
 30         }
 31     }
 32     /**
 33      * 中根次序
 34      */
 35     public void inorderTraversal() {
 36         System.out.println("中根次序遍历:");
 37         if(root != null) {
 38             root.inorder(root);
 39         }
 40     }
 41     /**
 42      * 后根次序
 43      */
 44     public void postorderTraversal() {
 45         System.out.println("后根次序遍历:");
 46         if(root != null) {
 47             root.postorder(root);
 48         }
 49     }
 50     /**
 51      * 通过先根遍历与中根遍历构造二叉树(1)
 52      */
 53     public TreeNode reConstructBinaryTree1(int[] pre, int[] in) {
 54         if(pre.length == 0 || in.length == 0) {
 55             return null;
 56         }
 57         TreeNode p = new TreeNode(pre[0]);
 58         for (int i = 0; i < in.length; i++) {
 59             if(pre[0] == in[i]) {
 60                 p.left = reConstructBinaryTree1(Arrays.copyOfRange(pre, 1, i+1), Arrays.copyOfRange(in, 0, i));
 61                 p.right = reConstructBinaryTree1(Arrays.copyOfRange(pre, i+1, pre.length), Arrays.copyOfRange(in, i+1, in.length));
 62             }
 63         }
 64         return p;
 65     }
 66     /**
 67      * 通过先根遍历与中根遍历构造二叉树(2)
 68      */
 69     public TreeNode reConstructBinaryTree(int[] pre, int[] in) {
 70         if(pre == null || in == null) {
 71             return null;
 72         }
 73         TreeNode p = null;
 74         int first;
 75         int n = pre.length;
 76         int k = 0;
 77         if(n > 0) {
 78             // 取第一个为根
 79             first = pre[0];
 80             p = new TreeNode(first);
 81             // 确定根结点在中根序列中的位置
 82             for (int i = 0; i < in.length; i++) {
 83                 if(in[i] == first) {
 84                     k = i;
 85                     break;
 86                 }
 87             }
 88             // 左子树
 89             int[] presubLeft = new int[k];
 90             int[] insubLeft = new int[k];
 91             // 先根
 92             for (int i = 1, j = 0; i <= k; i++, j++) {
 93                 presubLeft[j] = pre[i];
 94             }
 95             // 中根
 96             for (int i = 0, j = 0; i <= k-1; i++, j    ++) {
 97                 insubLeft[j] = in[i];
 98             }
 99             p.left = reConstructBinaryTree(presubLeft, insubLeft);
100             // 右子树
101             int[] presubRight = new int[n-1-k];
102             int[] insubRight = new int[n-1-k];
103             // 先根
104             for (int i = k+1, j = 0; i <= n-1; i++,j++) {
105                 presubRight[j] = pre[i];
106             }
107             // 中根
108             for (int i = k+1, j = 0; i <= n-1; i++,j++) {
109                 insubRight[j] = in[i];
110             }
111             p.right = reConstructBinaryTree(presubRight, insubRight);
112         }
113         return p;
114     }
115 }

测试类 

 1 /**
 2  * Copyright 2016 Zhengbin's Studio.
 3  * All right reserved.
 4  * 2016年7月16日 上午9:27:40
 5  */
 6 package Two;
 7 
 8 /**
 9  * @author zhengbinMac
10  *
11  */
12 public class Test {
13 
14     public static void main(String[] args) {
15         int[] pre = {1,2,4,3,5,6};
16         int[] in = {4,2,1,5,3,6};
17         Tree t = new Tree(pre, in);
18         t.inorderTraversal();
19         System.out.println();
20         t.postorderTraversal();
21         System.out.println();
22         t.preorderTraversal();
23     }
24 }

在线编程:

牛客网——《剑指Offer》-重建二叉树

原文地址:https://www.cnblogs.com/zhengbin/p/5677568.html