二叉树

0、二叉树结点的构造

 

1 public static class Node {
2         public int value;
3         public Node left;
4         public Node right;
5 
6         public Node(int data) {
7             this.value = data;
8         }
9 }

 

1、前序的非递归遍历:

 

栈中每次弹出的当前结点后:打印弹出结点val值,有右先压右,有左后压左

 1 public static void preOrderUnRecur(Node head) {
 2     System.out.print("pre-order: ");
 3     if (head != null) {
 4         Stack<Node> stack = new Stack<Node>();
 5         stack.add(head);
 6         while (!stack.isEmpty()) {
 7             head = stack.pop();
 8             System.out.print(head.value + " ");
 9             if (head.right != null) {
10                 stack.push(head.right);
11             }
12             if (head.left != null) {
13                 stack.push(head.left);
14             }
15         }
16     }
17     System.out.println();
18 }

 

2、中序的非递归遍历

 

当前结点不为空:压栈,当前结点往左走

当前结点为空:弹栈,打印弹出结点的val值,当前结点往右走

 1 public static void inOrderUnRecur(Node head) {
 2     System.out.print("in-order: ");
 3     if (head != null) {
 4         Stack<Node> stack = new Stack<Node>();
 5         while (!stack.isEmpty() || head != null) {
 6             if (head != null) {
 7                 stack.push(head);
 8                 head = head.left;
 9             } else {
10                 head = stack.pop();
11                 System.out.print(head.value + " ");
12                 head = head.right;
13             }
14         }
15     }
16     System.out.println();
17 }

 

3、后序的非递归遍历

 

已知前序是:中--左--右,先转换成:中--右--左,然后申请一个辅助栈颠倒成:左--右--中,接着遍历打印辅助栈内结点的val值

那么如何使用辅助栈颠倒成:左--右--中呢?

在弹栈的时候不打印结点val值而是将其压入辅助栈

 1 public static void posOrderUnRecur(Node head) {
 2     System.out.print("pos-order: ");
 3     if (head != null) {
 4         Stack<Node> s1 = new Stack<Node>();
 5         Stack<Node> s2 = new Stack<Node>();
 6         s1.push(head);
 7         while (!s1.isEmpty()) {
 8             head = s1.pop();
 9             s2.push(head);
10             if (head.left != null) {
11                 s1.push(head.left);
12             }
13             if (head.right != null) {
14                 s1.push(head.right);
15             }
16         }
17         while (!s2.isEmpty()) {
18             System.out.print(s2.pop().value + " ");
19         }
20     }
21     System.out.println();
22 }

 

4、判断二叉树是否完全相同

 

同样可以用来判断二叉树是否对称,如下所示:

      1 
    /    \
   2      2
  /  \    / \
3   4  4    3

 1 boolean isSameTree(TreeNode root1, TreeNode root2) {
 2     // 都为空的话,显然相同
 3     if (root1 == null && root2 == null) return true;
 4     // 一个为空,一个非空,显然不同
 5     if (root1 == null || root2 == null) return false;
 6     // 两个都非空,但 val 不一样也不行
 7     if (root1.val != root2.val) return false;
 8 
 9     // root1 和 root2 该比的都比完了
10     return isSameTree(root1.left, root2.left)
11         && isSameTree(root1.right, root2.right);
12 }

 

5、判断一个树是否为二叉搜索树

 

 1 boolean isValidBST(TreeNode root) {
 2     return isValidBST(root, null, null);
 3 }
 4 
 5 boolean isValidBST(TreeNode root, TreeNode min, TreeNode max) {
 6     if (root == null) return true;
 7     if (min != null && root.val <= min.val) return false;
 8     if (max != null && root.val >= max.val) return false;
 9     return isValidBST(root.left, min, root) 
10         && isValidBST(root.right, root, max);
11 }

 

6、在BST中查找数字target是否存在

 

1 boolean isInBST(TreeNode root, int target) {
2     if (root == null) return false;
3     if (root.val == target)
4         return true;
5     if (root.val < target) 
6         return isInBST(root.right, target);
7     if (root.val > target)
8         return isInBST(root.left, target);
9 }

 

7、在BST中插入一个数

 

 1 TreeNode insertIntoBST(TreeNode root, int val) {
 2     // 找到空位置插入新节点
 3     if (root == null) return new TreeNode(val);
 4     // if (root.val == val)
 5     //     BST 中一般不会插入已存在元素
 6     if (root.val < val) 
 7         root.right = insertIntoBST(root.right, val);
 8     if (root.val > val) 
 9         root.left = insertIntoBST(root.left, val);
10     return root;
11 }

 

8、在BST中删除一个数

 

情况 1:A 恰好是末端节点,两个子节点都为空,那么它可以当场去世了。

情况 2:A 只有一个非空子节点,那么它要让这个子节点接替自己的位置。

情况 3:A 有两个子节点,麻烦了,为了不破坏 BST 的性质,A 必须找到左子树中最大的那个节点,或者右子树中最小的那个节点来接替自己。这里我门用后者来解决这种情况。

 1 TreeNode deleteNode(TreeNode root, int key) {
 2     if (root == null) return null;
 3     if (root.val == key) {
 4         // 这两个 if 把情况 1 和 2 都正确处理了
 5         if (root.left == null) return root.right;
 6         if (root.right == null) return root.left;
 7         // 处理情况 3
 8         TreeNode minNode = getMin(root.right);
 9         root.val = minNode.val;
10         root.right = deleteNode(root.right, minNode.val);
11     } else if (root.val > key) {
12         root.left = deleteNode(root.left, key);
13     } else if (root.val < key) {
14         root.right = deleteNode(root.right, key);
15     }
16     return root;
17 }
18 
19 TreeNode getMin(TreeNode node) {
20     // BST 最左边的就是最小的
21     while (node.left != null) node = node.left;
22     return node;
23 }

 

posted on 2020-08-24 21:09  小小字节  阅读(98)  评论(0编辑  收藏  举报