Java multithreading implementation, concurrency and synchronization, [Java data structure and algorithm]

Binary tree refers to an ordered tree in which the degree of nodes in the tree is no more than 2. It is the simplest and most important tree. The recursive definition of binary tree is: a binary tree is an empty tree, or a non empty tree composed of a root node and two disjoint left and right subtrees called roots respectively; the left and right subtrees are also binary trees

Related terms:

  1. Node: contains a data element and several information pointing to the branches of the subtree

  2. Node degree: the number of subtrees a node has is called node degree

  3. Leaf node: also known as terminal node, node without subtree or node with zero degree

  4. Branch node: also known as non terminal node. Nodes with degree not zero are called non terminal nodes

  5. Degree of tree: the maximum degree of all nodes in the tree

  6. Node hierarchy: starting from the root node, it is assumed that the root node is layer 1 and the child nodes of the root node are layer 2, and so on. If a node is located in layer L, its child nodes are located in layer L + 1

  7. Tree depth: also known as the height of the tree. The maximum hierarchical value of all nodes in the tree is called the depth of the tree

  8. Ordered tree: if the order of each tree in the tree is in order, the tree is called ordered tree

  9. Unordered tree: if the order of each tree in the tree has no order, the tree is called unordered tree

    10. Forest: a forest is composed of m (m ≥ 0) disjoint trees. If the root node of a non empty tree is deleted, the tree becomes a forest, and the tree in the forest is composed of all the sub trees of the original root node

Special type:

  • Full binary tree: refers to a binary tree with a depth of K and 2^k - 1 nodes

  • Complete binary tree: set the depth of the binary tree as h, the number of nodes in other layers reaches the maximum except layer h, and all nodes in layer h are continuously concentrated on the far left. In other words, the n nodes contained in the tree correspond to the nodes numbered 1 to n in the full binary tree one by one

    • The left child node of the nth element is 2n

    • The right child node of the nth element is 2n + 1

    • The parent node of the nth element is (n - 1) / 2

nature:

  1. There are at most 2^(i - 1) points (i ≥ 1) on layer i of binary tree

  2. A binary tree with depth h contains at most 2^h - 1 nodes

  3. If there are n0 leaf nodes and n2 nodes with degree 2 in any binary tree, there must be n0 = n2 + 1

  4. The depth of a complete binary tree with n nodes is log2(x + 1), where X represents the largest integer not greater than n

  5. If a complete binary tree with n nodes is sequentially numbered (1 ≤ i ≤ n), then for the node numbered i (i ≥ 1):

    When i = 1, the node is the root and it has no parents

    When I > 1, the number of the parent node of the node is i / 2

    If 2i < n, there is a left node numbered 2i, otherwise there is no left node

    If 2i + 1 ≤ n, there is a right node numbered 2i + 1, otherwise there is no right node

2. Traversing binary tree

Preorder traversal binary tree

Idea:

After accessing a node, print the node and continue to traverse its left and right subtrees

Traversal order:

GDAFEMHZ

Code implementation:

//Preorder traversal

public void preOrder(){

    //Print parent node

    System.out.println(this);

    //Recursive pre order traversal to the left subtree

    if (this.left != null){

        this.left.preOrder();

    }

    //Recursive right subtree preorder traversal

    if (this.right != null){

        this.right.preOrder();

    }

} 

Middle order traversal binary tree

Idea:

After accessing a node, temporarily store it. After traversing the left subtree, print the value of the node, and then traverse the right subtree

Traversal order:

ADEFGHMZ

Code implementation:

//Medium order traversal

public void infixOrder(){

    //Recursive traversal to the middle order of the left subtree

    if (this.left != null){

        this.left.infixOrder();

    }

    //Print parent node

    System.out.println(this);

    //Recursive traversal in right subtree

    if (this.right != null){

        this.right.infixOrder();

    }

} 

Subsequent traversal of binary tree

Idea:

After accessing a node, temporarily store it. After traversing the left and right subtrees, print the value of the node

Traversal order:

AEFDHZMG

Code implementation:

//Postorder traversal

public  void postOrder(){

    //Recursive postorder traversal to the left subtree

    if (this.left != null){

        this.left.postOrder();

    }

    //Recursive postorder traversal of right subtree

    if (this.right != null){

        this.right.postOrder();

    }

    //Print parent node

    System.out.println(this);

} 

Hierarchical traversal binary tree

Idea:

Establish a circular queue. First put the root node of the binary tree into the queue, then out of the queue and access the root node. If it has a left subtree, put the root node of the left subtree in the queue; if it has a right subtree, put the root node of the right subtree in the queue. Then go out of the queue and access the out of queue node. Repeat until the queue is empty

Traversal order:

ADMAFHZ

Code implementation:

//level traversal 

    public void levelOrder(){

        ArrayDeque<HeroNode> queue = new ArrayDeque<>(20);

        //First, add the root node to the queue

        queue.add(this);

        //Traversal binary tree

        while(!queue.isEmpty()){

            HeroNode tempNode = queue.poll();

            System.out.println(tempNode);



            if (tempNode.left != null){

                queue.add(tempNode.left);

            }

            if (tempNode.right != null){

                queue.add(tempNode.right);

            }

        }

    } 

3. Find binary tree

Preorder search Binary Tree

Idea:

  1. First, compare the root nodes. If they are equal, return directly. Otherwise, search in the left recursive preamble

  2. If it is found by left recursion, it returns directly; otherwise, it is found by right recursion

  3. If the right recursion finds the return, otherwise it returns null

Node H found

Number of comparisons:

7

Code implementation:

//Preorder traversal

    public HeroNode preOrdersearch(int no){

        System.out.println("Enter preorder traversal");

        //Compare whether the current node is

        if (this.no == no){

            return this;

        }

        //1. Judge whether the left child node of the current node is empty. If not, recursive preorder search

        //2. If the left recursive preorder search finds a node, it returns

        HeroNode resNode = null;

        if (this.left != null){

            resNode = this.left.preOrdersearch(no);

        }

        if (resNode != null){   //That means we found the left subtree

            return resNode;

        }

        //1. Left recursive preorder search. If a node is found, it returns. Continue to judge whether or not

        //2. Whether the right child node of the current node is empty. If it is not empty, continue to search in the right recursive preamble

        if (this.right != null){

            resNode = this.right.preOrdersearch(no);

        }

        return resNode;

    } 

Middle order search Binary Tree

Idea:

  1. First, left recursive search. If it is found, it returns directly. Otherwise, it is compared with the root node

  2. If the comparison is equal, return directly, otherwise right recursive middle order search

  3. Returns if the right recursion is found, otherwise returns null

Find H node

Number of comparisons:

6

Code implementation:

//Medium order traversal

    public HeroNode infixOrderSearch(int no){

        //Judge whether the left child node of the current node is empty. If it is not empty, search in recursive middle order

        HeroNode resNode = null;

        if(this.left != null){

            resNode = this.left.infixOrderSearch(no);

        }

        if (resNode != null){

            return resNode;

        }

        System.out.println("Enter middle order traversal");

        //If found, it returns. If not found, it is compared with the current node. If yes, it returns the current node

        if (this.no == no){

            return this;

        }

        //Otherwise, continue the middle order search of right recursion

        if (this.right != null){

            resNode = this.right.infixOrderSearch(no);

        }

        return resNode;

    } 

Postorder search Binary Tree

Idea:

  1. First, the left recursive search. If it is found, it returns directly. Otherwise, the right recursive middle order search

  2. If the right recursion is found, it returns directly. Otherwise, it is compared with the root node

  3. Returns NULL if the comparison is not equal

Find H node

Number of comparisons:

5

Code implementation:

//Postorder traversal

    public HeroNode postOrderSearch(int no){

        //Judge whether the left child node of the current node is empty. If it is not empty, it will be searched recursively

        HeroNode resNode = null;

        if (this.left != null){

            resNode = this.left.postOrderSearch(no);

        }

        if (resNode != null){   //Description found in the left subtree

            return resNode;

        }

        //If the left subtree is not found, the right subtree recursively performs a post order traversal search

        if (this.right != null){

            resNode = this.right.postOrderSearch(no);

        }

        if (resNode != null){

            return resNode;

        }

        System.out.println("Enter post order traversal");

        //If the left and right subtrees are not found, compare the current node

        if (this.no == no){

            return this;

        }

        return resNode;

    } 

4. Delete node from binary tree

Idea:

  • If the deleted node is the root node, it is equivalent to setting the binary tree empty

  • If the deleted node is a non leaf node, the subtree is deleted

  • If the deleted node is a leaf node, delete the node

  • Because our binary tree is unidirectional, we can only judge whether the child nodes of the current node need to be deleted

  1. If the left child node of the current node is not empty and the left child node is the node to be deleted, execute this Left = null and return

  2. If the right child node of the current node is not empty and the left child node is the node to be deleted, execute this Right = null and return

  3. If there is no return in steps 1 and 2, we need to delete the left subtree recursively

  4. If there is still no return in step 3, recursively delete the right subtree

5. Binary tree synthesis example

code:

package com.sisyphus.tree;



import java.util.ArrayDeque;



/**

 * @Description: Binary tree$

 * @Param: $

 * @return: $

 * @Author: Sisyphus

 * @Date: 7/23$

 */

public class BinaryTreeDemo {

    public static void main(String[] args) {

        //First create a binary tree

        BinaryTree binaryTree = new BinaryTree();

        //Create required nodes

        HeroNode root = new HeroNode(1, "Song Jiang");

        HeroNode node2 = new HeroNode(2, "Wu Yong");

        HeroNode node3 = new HeroNode(3, "Lu Junyi");

        HeroNode node4 = new HeroNode(4, "Lin Chong");

        HeroNode node5 = new HeroNode(5, "Guan Sheng");



        //Note: we first create the binary tree manually, and then we learn to create the binary tree recursively

        root.setLeft(node2);

        root.setRight(node3);

        node3.setRight(node4);

        node3.setLeft(node5);

        binaryTree.setRoot(root);



        System.out.println("Preorder traversal"); //12354

        binaryTree.preOrder();



        System.out.println("Medium order traversal"); //21534

        binaryTree.infixOrder();



        System.out.println("Postorder traversal"); //25431

        binaryTree.postOrder();



        //Preorder traversal

        System.out.println("Preorder traversal");

        HeroNode resNode = binaryTree.preOrderSearch(5);

        if (resNode != null){

            System.out.printf("Yes, the information is no=%d name=%s",resNode.getNo(),resNode.getName());

            System.out.println();

        }else{

            System.out.printf("Can't find no=%d Hero of",5);

            System.out.println();

        }

        //Medium order traversal

        System.out.println("Medium order traversal");

        resNode = binaryTree.infixOrderSearch(5);

        if (resNode != null){

            System.out.printf("Yes, the information is no=%d name=%s",resNode.getNo(),resNode.getName());

            System.out.println();

        }else{

            System.out.printf("Can't find no=%d Hero of",5);

            System.out.println();

        }

        //Postorder traversal

        System.out.println("Postorder traversal");

        resNode = binaryTree.postOrderSearch(5);

        if (resNode != null){

            System.out.printf("Yes, the information is no=%d name=%s",resNode.getNo(),resNode.getName());

            System.out.println();

        }else{

            System.out.printf("Can't find no=%d Hero of",5);

            System.out.println();

        }



        System.out.println("===================================================");



        //Test delete node

        System.out.println("Pre sequence traversal before deletion");

        binaryTree.preOrder();

        binaryTree.delNode(5);

        System.out.println("After deletion, the preamble traverses");

        binaryTree.preOrder();



        System.out.println("======================================================");

        System.out.println("level traversal ");

        binaryTree.levelOrder();



    }

}



//Define BinaryTree

class BinaryTree{

    private HeroNode root;



    public void setRoot(HeroNode root){

        this.root = root;

    }



    //Delete Vertex 

    public void delNode(int no){

        if (root != null){

            //If there is only one root node, judge whether root is the node to be deleted immediately

            if (root.getNo() == no){

                root = null;

            }else{

                //Recursive deletion

                root.delNode(no);

            }

        }else{

            System.out.println("The tree is empty and cannot be deleted");

        }

    }



    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



    //ergodic



    //Preorder traversal

    public void preOrder(){

        if (this.root != null){

            this.root.preOrder();

        }else{

            System.out.println("The current binary tree is empty and cannot be traversed");

        }

    }

    //Medium order traversal

    public void infixOrder(){

        if (this.root != null){

            this.root.infixOrder();

        }else{

            System.out.println("The current binary tree is empty and cannot be traversed");

        }

    }

    //Postorder traversal

    public void postOrder(){

        if (this.root != null){

            this.root.postOrder();

        }else{

            System.out.println("The current binary tree is empty and cannot be traversed");

        }

    }

    //level traversal 

    public void levelOrder(){

        if (this.root != null){

            this.root.levelOrder();

        }else{

            System.out.println("The current binary tree is empty and cannot be traversed");

        }

    }



    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



    //lookup



    //Preorder traversal

    public HeroNode preOrderSearch(int no){

        if (root != null){

            return root.preOrdersearch(no);

        }else{

            return null;

        }

    }

    //Medium order traversal

    public HeroNode infixOrderSearch(int no){

        if (root != null){

            return root.infixOrderSearch(no);

        }else{

            return null;

        }

    }

    //Postorder traversal

    public HeroNode postOrderSearch(int no){

        if (root != null){

            return root.postOrderSearch(no);

        }else{

            return null;

        }

    }

}



//Create the HeroNode node first

class HeroNode{

    private int no;

    private String name;

    private HeroNode left;

    private HeroNode right;



    public HeroNode(int no, String name) {

        this.no = no;

        this.name = name;

    }



    public int getNo() {

        return no;

    }



    public void setNo(int no) {

        this.no = no;

    }



    public String getName() {

        return name;

    }



    public void setName(String name) {

        this.name = name;

    }



    public HeroNode getLeft() {

        return left;

    }



    public void setLeft(HeroNode left) {

        this.left = left;

    }



    public HeroNode getRight() {

        return right;

    }



    public void setRight(HeroNode right) {

        this.right = right;

    }



    @Override

    public String toString() {

        return "HeroNode{" +

                "no=" + no +

                ", name='" + name + '\'' +

                '}';

    }



    //Recursively delete nodes

    public void delNode(int no){

        if (this.left != null && this.left.no == no){

            this.left = null;

            return;

        }

        if (this.right != null && this.right.no == no){

            this.right = null;

            return;

        }

        if (this.left != null){

            this.left.delNode(no);

        }

        if (this.right != null){

            this.right.delNode(no);

        }

    }



    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



    //ergodic



    //Preorder traversal

    public void preOrder(){

        //Print parent node

        System.out.println(this);

        //Recursive pre order traversal to the left subtree

        if (this.left != null){

            this.left.preOrder();

        }

        //Recursive right subtree preorder traversal

        if (this.right != null){

            this.right.preOrder();

        }

    }

    //Medium order traversal

    public void infixOrder(){

        //Recursive traversal to the middle order of the left subtree

        if (this.left != null){

            this.left.infixOrder();

        }

        //Print parent node

        System.out.println(this);

        //Recursive traversal in right subtree

        if (this.right != null){

            this.right.infixOrder();

        }

    }

    //Postorder traversal

    public void postOrder(){

        //Recursive postorder traversal to the left subtree

        if (this.left != null){

            this.left.postOrder();

        }

        //Recursive postorder traversal of right subtree

        if (this.right != null){

            this.right.postOrder();

        }

        //Print parent node

        System.out.println(this);

    }

    //level traversal 

    public void levelOrder(){

        ArrayDeque<HeroNode> queue = new ArrayDeque<>(20);

        //First, add the root node to the queue

        queue.add(this);

        //Traversal binary tree

        while(!queue.isEmpty()){

            HeroNode tempNode = queue.poll();

            System.out.println(tempNode);



            if (tempNode.left != null){

                queue.add(tempNode.left);

            }

            if (tempNode.right != null){

                queue.add(tempNode.right);

            }

        }

    }



    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



    //lookup



    //Preorder traversal

    public HeroNode preOrdersearch(int no){

        System.out.println("Enter preorder traversal");

        //Compare whether the current node is

        if (this.no == no){

            return this;

        }

        //1. Judge whether the left child node of the current node is empty. If not, recursive preorder search

        //2. If the left recursive preorder search finds a node, it returns

        HeroNode resNode = null;

        if (this.left != null){

            resNode = this.left.preOrdersearch(no);

        }

        if (resNode != null){   //That means we found the left subtree

            return resNode;

        }

        //1. Left recursive preorder search. If a node is found, it returns. Continue to judge whether or not

        //2. Whether the right child node of the current node is empty. If it is not empty, continue to search in the right recursive preamble

        if (this.right != null){

            resNode = this.right.preOrdersearch(no);

        }

        return resNode;

    }

    //Medium order traversal

    public HeroNode infixOrderSearch(int no){

        //Judge whether the left child node of the current node is empty. If it is not empty, search in recursive middle order

        HeroNode resNode = null;

        if(this.left != null){

            resNode = this.left.infixOrderSearch(no);

        }

        if (resNode != null){

            return resNode;

        }

        System.out.println("Enter middle order traversal");

        //If found, it returns. If not found, it is compared with the current node. If yes, it returns the current node

        if (this.no == no){

            return this;

        }

        //Otherwise, continue the middle order search of right recursion

        if (this.right != null){

            resNode = this.right.infixOrderSearch(no);

        }

        return resNode;

    }

    //Postorder traversal

    public HeroNode postOrderSearch(int no){

        //Judge whether the left child node of the current node is empty. If it is not empty, it will be searched recursively

        HeroNode resNode = null;

        if (this.left != null){

            resNode = this.left.postOrderSearch(no);

        }

        if (resNode != null){   //Description found in the left subtree

            return resNode;

        }


Keywords: Java Back-end Interview Programmer

Added by jsscart on Sun, 02 Jan 2022 23:42:31 +0200