Various operations (non-recursive and recursive traversal, the depth of the tree, the node number, etc.) of the binary tree

The establishment of a binary tree

First given node structure:

static class Node {
    public int val;
    public Node left;
    public Node right;

    public Node(int val) {
        this.val = val;
    }
}
复制代码

Two options to create ways:

  • The binary tree can be recursively subscript relationship around binary tree root and child nodes, binary level input node;
  • Sequence binary tree (note to enter an empty tree -1) may also be used prior to the input stream;

1, the subscript relationship

// given a arr to build
static Node createTree(int arr[], int i) {
    if (i >= arr.length || arr[i] == -1)
        return null;
    Node root = new Node(arr[i]);
    root.left = createTree(arr, 2 * i + 1);
    root.right = createTree(arr, 2 * i + 2);
    return root;
}
复制代码

Substantially as follows:

2, the preamble input (CIN) to establish

// cin method	
static Node buildTree(Scanner cin) {
    Node root = null;
    int data = cin.nextInt();
    if (data != -1) {
        root = new Node(data);
        root.left = buildTree(cin);
        root.right = buildTree(cin);
    }
    return root;
}
复制代码

Process is as follows:

Preorder traversal

1, the preamble recursive

static void preOrder(Node T) {
    if (T == null)
        return;
    System.out.print(T.val + " ");
    preOrder(T.left);
    preOrder(T.right);
}
复制代码

2, the preamble nonrecursive

Preorder traversal order:  root -> left subtree -> right subtree , so for the root node is available, direct access, after completion of access, access to the left subtree in the same manner, then access right sub tree, as follows:

  • If the current node pis not empty, access node p, and the node ponto the stack, and continue to visit the left subtree (until the left subtree is empty);
  • Otherwise, the top element from the stack, the stack and access the elements of the right subtree;
  • Until the stack is empty and pempty, the end of the cycle.

Code:

static void iterativePre(Node root) {
    Stack<Node> s = new Stack<>();
    Node p = root;
    while (!s.empty() || p != null) {
        if (p != null) {//也可以写一个while循环,直到左子树为空
            s.push(p);
            System.out.print(p.val + " ");
            p = p.left;
        } else {
            p = s.pop();
            p = p.right;
        }
    }
}
复制代码

You can also have access to the upper left subtree is empty written a whilecycle:

static void iterativePre2(Node root) {
    Stack<Node> s = new Stack<>();
    Node p = root;
    while (!s.empty() || p != null) {
        while (p != null) { // while循环,直到左子树为空
            s.push(p);
            System.out.print(p.val + " ");
            p = p.left;
        }
        p = s.pop();
        p = p.right;
    }
}
复制代码

There is another way to write is: 

  • First root node stack, and then popping each element of a first visit to this element, and then if it's right subtree exist, stack, if it's left subtree there is also the stack;
  • Why the first into the right subtree of it, because, in a preorder traversal -> Left -> Right, but you can stack in reverse order, so first the right and then left;

This method is embodied in a subsequent traversal of the dual-stack method, that this is only slight modifications.

static void iterativePre3(Node root) {
    if (root == null)
        return;
    Node p = root;
    Stack<Node> stack = new Stack<>();
    stack.add(p);
    while (!stack.isEmpty()) {
        p = stack.pop();
        System.out.print(p.val + " ");
        if (p.right != null)// 先右再左即可
            stack.push(p.right);
        if (p.left != null)
            stack.push(p.left);
    }
}
复制代码

Preorder

1, in order recursive

static void inOrder(Node T) {
    if (T == null)
        return;
    inOrder(T.left);
    System.out.print(T.val + " ");
    inOrder(T.right);
}
复制代码

2, in order nonrecursive

Preorder:  left subtree -> Root -> right subtree , as follows:

  • The current node is not empty != null, pushed onto the stack (and various preorder traversal is not required to print), the current node to the left;
  • The current node is empty == null, and a print out (printed here), the current node from the stack to the right;

Until the stack is empty and p is null, the end of the cycle.

/**
* 1)、当前节点不空(!=null),压入栈中(和前序遍历不同的是,不需要打印),当前节点向左;
* 2)、当前节点为空(==null),从栈中拿出一个并且打印(在这里打印) ,当前节点向右;
*/
static void iterativeIn(Node root) {
    if (root == null)
        return;
    Stack<Node> s = new Stack<>();
    Node p = root;
    while (!s.empty() || p != null) {
        if (p != null) {
            s.push(p);
            p = p.left;
        } else {
            p = s.pop();
            System.out.print(p.val + " "); //在这里打印
            p = p.right;
        }
    }
}
复制代码

Similarly, the children have been left where you can also access into whlie:

static void iterativeIn2(Node root) {
    if (root == null)
        return;
    Stack<Node> s = new Stack<>();
    Node p = root;
    while (!s.empty() || p != null) {
        while (p != null) { //这里改成while
            s.push(p);
            p = p.left;
        }
        p = s.pop();
        System.out.print(p.val + " "); //在这里打印
        p = p.right;
    }
}
复制代码

Postorder

1, the recursive sequence

static void postOrder(Node T) {
    if (T == null)
        return;
    postOrder(T.left);
    postOrder(T.right);
    System.out.print(T.val + " ");
}
复制代码

2, the non-recursive sequence

1) dual-stack method

This is actually a non-recursive preamble ( iterativePre3) a little bit of improvement.

  • First, a preorder traversal stack ( iterativePre3) order is to the left and then the right ;
  • At this time, we can do turn first left then right , so the order of traversal can be done  "in the right-left" and the subsequent traversal is  "right and left" , just in front of the opposite, so we then use a stack inversion save it ;

Code:

/**
* 非递归后续1(双栈法解决非递归后续)
* 后续遍历是要实现&emsp;&emsp;&emsp;左->右->中
* 这个方法和前序遍历的第二种方法&emsp;只是多了一个栈而已
* 因为&emsp;前序遍历是  中->左->右&emsp;&emsp;压栈顺序是 右->左
* 这样,我们就很容易实现&emsp;中->右->左遍历&emsp;&emsp;压栈顺序是&emsp;左->右
* 而后续遍历是要实现  左->右->中,
* 我们把上面的&emsp;&emsp;中右左&emsp;压入到另一个栈中&emsp;就实现了&emsp;左右中
*/
static void iterativePos(Node root) {
    Stack<Node> s = new Stack<>(), s2 = new Stack<>();
    Node p;
    s.push(root);
    while (!s.empty()) {
        p = s.pop();
        s2.push(p);
        if (p.left != null) s.push(p.left); //这里是先左再右  (非递归前序是先右再左)
        if (p.right != null) s.push(p.right);
    }
    while (!s2.empty())
        System.out.print(s2.pop().val + " ");
}
复制代码

2), provided prenode

Process is as follows:

  • For any node p, it first stack;
  • The case can access: ① If the pleft child and right child does not exist, you can access it directly. ② or pthe presence of left child or right child, but a child left and right children have been visited, you can also access the node directly;
  • In both cases if not, then the right child and left child turn the stack . This ensures that every time you take the top element, the child was left in front of the access right child, root node in the left child and right child visit after being accessed;

Code:

/*** 非递归后续2(设置pre结点) */
static void iterativePos2(Node root) {
    Node cur, pre = null;
    Stack<Node> s = new Stack<>();
    s.push(root);
    while (!s.empty()) { 
        cur = s.peek();
        // 两种可以访问的情况
        if ((cur.left == null && cur.right == null) ||
            ((pre != null) && (pre == cur.left || pre == cur.right))) {
            System.out.print(cur.val + " ");
            s.pop();
            pre = cur;
        } else {
            if (cur.right != null) s.push(cur.right);
            if (cur.left != null) s.push(cur.left);
        }
    }
}
复制代码

Traverse the level

Very simple. BFS queue to use, each complete visit p, if there is a child around, then into the team until the team empty;

static void levelOrder(Node root) {
    if (root == null)
        return;
    Queue<Node> queue = new LinkedList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        Node now = queue.poll();
        System.out.print(now.val + " ");
        if (now.left != null) queue.add(now.left);
        if (now.right != null) queue.add(now.right);
    }
}
复制代码

Looking tree has no node value x

Recursive two conditions, one is not found empty representatives, he found the words directly returned, otherwise the recursive search about sub-tree.

//查找某个值为x的结点
static Node search(Node T, int x) {
    if (T == null)
        return null;
    if (T.val == x)
        return T;
    else {
        if (search(T.left, x) == null)
            return search(T.right, x);
        else
            return search(T.left, x);
    }
}
复制代码

Count the number of nodes in the tree

Tree root node equal to the number (1) the number of tree nodes point number + + right subtree left child, can be solved recursively.

source-java
//统计结点个数
static int count(Node T) {
    if (T == null)
        return 0;
    else
        return count(T.left) + count(T.right) + 1;
}
复制代码

Calculated height of the tree

Also recursive solution, coupled with relatively high height of the root is about sub-tree of the tree.

source-java
//计算二叉树的深度
static int depth(Node T) {
    if (T == null)
        return 0;
    return Math.max(depth(T.left), depth(T.right)) + 1;
}
复制代码

Analyzing two trees are not equal

Recursive solution is equal to two trees, both equal to the value of the root node, and the left and right sub-tree should be equal.

source-java
//判断两棵树是不是相等
static boolean is_SameTree(Node T1, Node T2) {
    if (T1 == null && T2 == null)
        return true;
    else {
        return T1 != null && T2 != null && T1.val == T2.val
            && is_SameTree(T1.left, T2.left) && is_SameTree(T1.right, T2.right);
    }
}
复制代码

No welcome public attention: the old boy's growth path, offer a weekly selection of dry goods on a regular basis!

Guess you like

Origin juejin.im/post/5e06053551882512513545f3