Data structure - binary tree

Keywords: data structure Binary tree

1. Why do you need a tree data structure?

  • Analysis of array storage mode
    • Advantages: it is fast to access elements by subscript. For ordered arrays, binary search can also be used to improve the retrieval speed.
    • Disadvantages: if a specific value is to be retrieved, or the inserted value (in a certain order) will move as a whole, the efficiency is very low [schematic diagram]

  • Analysis of chain storage mode
    • Advantages: the array storage method is optimized to a certain extent. For example, when inserting a numerical node, you only need to link the inserted node to the linked list, and the deletion efficiency is also very good
    • Disadvantages: when searching, the efficiency is still low, for example (to retrieve a value, you need to traverse from the beginning of the node) [schematic diagram]

  • Tree storage mode analysis
    It can improve the efficiency of data storage and reading. For example, using binary sort tree can not only ensure the speed of data retrieval, but also ensure the speed of data insertion, deletion and modification [schematic diagram]

  • Tree diagram


Common terms for trees

-  node
-  Root node
- Parent node
- Child node
- Leaf node(Node without child nodes)
- Weight of node(Node value)
- route(from root Route from node to node)
- layer
- subtree
- Tree height(Max layers )
- Forest: many sub trees form a forest

2. Concept of binary tree

  • Concept of binary tree

    1. There are many kinds of trees. Each node can only have two child nodes at most, which is called a binary tree

    2. The child nodes of binary tree are divided into left node and right node

    3. Sketch Map

    4. If all leaf nodes of the binary tree are in the last layer, and the total number of nodes = 2 ^ n - 1, n is the number of layers, we call it a full binary tree

    5. If all leaf nodes of the binary tree are in the last or penultimate layer, and the leaf nodes of the last layer are continuous on the left and the leaf nodes of the penultimate layer are continuous on the right, we call it a complete binary tree

3. Traversal description of binary tree

Use pre order, middle order and post order to traverse the binary tree

1. Preorder traversal: first enter the parent node, and then traverse the left and right subtrees
2. Medium order traversal: first traverse the left subtree, then output the parent node, and then traverse the right subtree
3. Post order traversal: first traverse the left subtree, then traverse the right subtree, and then output the parent node

💻 code implementation

package com.yao.tree;

/**
 * @Author: Yao
 * @Date: 2021/10/19 11:30
 */
public class BinaryTreeErgodic {
    public static void main(String[] args) {

        //Define binary tree
        BinaryTree binaryTree = new BinaryTree();

        HeroNode root = new HeroNode(1, "Song Jiang");
        HeroNode heroNode2 = new HeroNode(2, "Wu Yong");
        HeroNode heroNode3 = new HeroNode(3, "Lu Junyi");
        HeroNode heroNode4 = new HeroNode(4, "Lin Chong");
        HeroNode heroNode5 = new HeroNode(5, "Guan Sheng");
        binaryTree.setRoot(root);
        root.setLeft(heroNode2);
        root.setRight(heroNode3);
        heroNode3.setLeft(heroNode5);
        heroNode3.setRight(heroNode4);

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

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

        System.out.println("Postorder traversal..");
        binaryTree.postOrder();
    }
}

//Create a BinaryTree binary tree
class BinaryTree{

    //Create a root node
    private HeroNode root;

    public void setRoot(HeroNode root) {
        this.root = root;
    }

    //Implementation of preorder traversal
    public void preOrder(){
        if (this.root != null){
            this.root.preOrder();
        }else{
            System.out.println("Binary tree is empty and cannot be traversed...");
        }
    }

    //Implementation of sequence traversal
    public void midOrder(){
        if (this.root != null){
            this.root.midOrder();
        }else{
            System.out.println("Binary tree is empty and cannot be traversed...");
        }
    }

    //Realize post order traversal
    public void postOrder(){
        if (this.root != null){
            this.root.postOrder();
        }else {
            System.out.println("Binary tree is empty and cannot be traversed...");
        }
    }


}

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 + '\'' +
                '}';
    }


    /**
     * Binary tree preorder traversal
     */
    public void preOrder(){
        System.out.println(this);
        //If the left subtree of the current node is not empty, it is traversed recursively first
        if (this.left != null){
            this.left.preOrder();
        }
        //If the right subtree of the current node is not empty, it is traversed recursively first
        if (this.right != null){
            this.right.preOrder();
        }
    }

    /**
     * Middle order traversal of binary tree
     */
    public void midOrder(){
        //If the left subtree of the current node is not empty, it will be traversed in recursive order
        if (this.left != null){
            this.left.midOrder();
        }
        //Output current node
        System.out.println(this);
        //If the right subtree of the current node is not empty, it will be traversed in recursive order
        if(this.right != null){
            this.right.midOrder();
        }
    }

    /**
     * Binary Tree Postorder Traversal 
     */
    public void postOrder(){
        //If the left subtree of the current node is not empty, it will be traversed recursively
        if (this.left != null){
            this.left.postOrder();
        }
        //If the right subtree of the current node is not empty, it will be traversed recursively
        if (this.right != null){
            this.right.postOrder();
        }
        //Output current node
        System.out.println(this);
    }

}

4. Binary tree to find the specified node

  • Write pre order search, middle order search and post order search methods
  • Three search methods are used to find the node with heroNo = 5
  • Analyze three search methods
  • Train of thought analysis diagram

💻 code implementation

package com.yao.tree;

/**
 * @Author: Yao
 * @Date: 2021/10/20 9:48
 */
public class BinaryTreeSearch {
    public static void main(String[] args) {
        BinaryTree2 binaryTree2 = new BinaryTree2();
        HeroNode2 root = new HeroNode2(1, "Song Jiang");
        HeroNode2 heroNode2 = new HeroNode2(2, "Wu Yong");
        HeroNode2 heroNode3 = new HeroNode2(3, "Lu Junyi");
        HeroNode2 heroNode4 = new HeroNode2(4, "Lin Chong");
        HeroNode2 heroNode5 = new HeroNode2(5, "Guan Sheng");
        binaryTree2.setRoot(root);
        root.setLeft(heroNode2);
        root.setRight(heroNode3);
        heroNode3.setLeft(heroNode5);
        heroNode3.setRight(heroNode4);

        //Pre order traversal search no=5
        System.out.println(binaryTree2.preSearch(5));
        //Middle order traversal search no=5
        System.out.println(binaryTree2.midSearch(5));
        //Post order traversal search no=5
        System.out.println(binaryTree2.postSearch(5));

    }
}

//Create a binary tree
class BinaryTree2{
    private HeroNode2 root;

    public void setRoot(HeroNode2 root) {
        this.root = root;
    }

    //Binary tree preorder search
    public HeroNode2 preSearch(int no){

        if (this.root != null){
            return this.root.preOrderSearch(no);
        }else{
            System.out.println("The binary tree is empty.....");
            return null;
        }
    }

    //Ordered search in binary tree
    public HeroNode2 midSearch(int no){
        if (this.root != null){
            return this.root.midOrderSearch(no);
        }else{
            System.out.println("The binary tree is empty.....");
            return null;
        }
    }

    //Binary tree postorder search
    public HeroNode2 postSearch(int no){
        if (this.root != null){
            return this.root.postOrderSearch(no);
        }else{
            System.out.println("The binary tree is empty.....");
            return null;
        }
    }


}


//Create node of binary tree
class HeroNode2{

    private  int no;

    private String name;

    private HeroNode2 left;

    private HeroNode2 right;

    public HeroNode2(int no, String name){
        this.no = no;
        this.name = name;
    }

    public void setNo(int no) {
        this.no = no;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setLeft(HeroNode2 left) {
        this.left = left;
    }

    public void setRight(HeroNode2 right) {
        this.right = right;
    }

    public int getNo() {
        return no;
    }

    public String getName() {
        return name;
    }

    public HeroNode2 getLeft() {
        return left;
    }

    public HeroNode2 getRight() {
        return right;
    }

    @Override
    public String toString() {
        return "HeroNode2{" +
                "no=" + no +
                ", name='" + name + '\'' +
                '}';
    }


    //Preorder search of binary tree
    public HeroNode2 preOrderSearch(int no){
        HeroNode2 resNode = null;
        //Judge whether the current node is the node to be found. If so, return
        System.out.println("Enter preorder search traversal....");
        if (this.no == no){
            return this;
        }
        //If it is not, judge whether the left subtree of the current node is empty. If it is not empty, perform sequential recursion, and return if found
        if (this.left != null){
            resNode = this.left.preOrderSearch(no);
        }
        if (resNode != null){ //Description found
            return resNode;
        }
        //If the left subtree is not found, judge whether the right subtree of the current node is empty. If it is not empty, perform preorder recursion, and return when found
        if (this.right != null){
           resNode = this.right.preOrderSearch(no);
        }
        return resNode;

    }

    //Middle order search of binary tree
    public HeroNode2 midOrderSearch(int no){
        HeroNode2 resNode = null;
        //First, judge whether the left subtree of the current node is empty. If it is not empty, perform medium order recursion, and return when it is found
        if (this.left != null){
            resNode = this.left.midOrderSearch(no);
        }
        if (resNode != null){
            return resNode;
        }
        //If the left subtree of the current node is not found, it is compared with the current node and returned if found
        System.out.println("Enter middle order search traversal....");
        if (this.no == no){
            return this;
        }
        //If the current node is not found, judge whether the right subtree of the current node is empty. If it is not empty, perform medium order recursion, and return when found
        if (this.right != null){
            resNode = this.right.midOrderSearch(no);
        }
        return resNode;
    }

    //Post order search of binary tree
    public HeroNode2 postOrderSearch(int no){
        HeroNode2 resNode = null;
        //Judge whether the left subtree of the current node is empty. If you are not empty, perform post order recursion and return when found
        if (this.left != null){
            resNode = this.left.postOrderSearch(no);
        }
        if (resNode != null){
            return resNode;
        }
        //If the right subtree of the current node is not found, judge whether the left subtree of the current node is empty. If not, perform subsequent recursion
        if (this.right != null){
            resNode = this.right.postOrderSearch(no);
        }
        //If the right subtree of the current node is not found, it is compared with the current node
        System.out.println("Enter post order search traversal....");
        if (this.no == no){
            return this;
        }

        return resNode;
    }

}

5. Delete node from binary tree

  • If the deleted node is a leaf node, delete the node
  • If the deleted node is a non leaf node, the subtree is deleted
  • Delete thought analysis

💻 code implementation

package com.yao.tree;

/**
 * @Author: Yao
 * @Date: 2021/10/19 11:30
 */
public class BinaryTreeErgodic {
    public static void main(String[] args) {

        //Define binary tree
        BinaryTree binaryTree = new BinaryTree();

        HeroNode root = new HeroNode(1, "Song Jiang");
        HeroNode heroNode2 = new HeroNode(2, "Wu Yong");
        HeroNode heroNode3 = new HeroNode(3, "Lu Junyi");
        HeroNode heroNode4 = new HeroNode(4, "Lin Chong");
        HeroNode heroNode5 = new HeroNode(5, "Guan Sheng");
        binaryTree.setRoot(root);
        root.setLeft(heroNode2);
        root.setRight(heroNode3);
        heroNode3.setLeft(heroNode5);
        heroNode3.setRight(heroNode4);

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

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

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

        System.out.println("------------------------");
        System.out.println("Preorder traversal ..");
        binaryTree.preOrder();
        binaryTree.delNode(3);
        System.out.println("Preorder traversal ..");
        binaryTree.preOrder();
    }
}

//Create a BinaryTree binary tree
class BinaryTree{

    //Create a root node
    private HeroNode root;

    public void setRoot(HeroNode root) {
        this.root = root;
    }

    //Implementation of preorder traversal
    public void preOrder(){
        if (this.root != null){
            this.root.preOrder();
        }else{
            System.out.println("Binary tree is empty and cannot be traversed...");
        }
    }

    //Implementation of sequence traversal
    public void midOrder(){
        if (this.root != null){
            this.root.midOrder();
        }else{
            System.out.println("Binary tree is empty and cannot be traversed...");
        }
    }

    //Realize post order traversal
    public void postOrder(){
        if (this.root != null){
            this.root.postOrder();
        }else {
            System.out.println("Binary tree is empty and cannot be traversed...");
        }
    }


    public void delNode(int no){
        //If the root node is not empty and is the node to be deleted, delete it directly
        if (this.root != null && this.root.getNo() == no){
            root = null;
            return;
        }else if(this.root != null){ //If the root node is not empty and is not the node to be deleted, judge the left and right subtrees
            this.root.delNode(no);
        }else {
            System.out.println("The binary tree is empty.....");
        }
    }


}

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 + '\'' +
                '}';
    }


    /**
     * Binary tree preorder traversal
     */
    public void preOrder(){
        System.out.println(this);
        //If the left subtree of the current node is not empty, it is traversed recursively first
        if (this.left != null){
            this.left.preOrder();
        }
        //If the right subtree of the current node is not empty, it is traversed recursively first
        if (this.right != null){
            this.right.preOrder();
        }
    }

    /**
     * Middle order traversal of binary tree
     */
    public void midOrder(){
        //If the left subtree of the current node is not empty, it will be traversed in recursive order
        if (this.left != null){
            this.left.midOrder();
        }
        //Output current node
        System.out.println(this);
        //If the right subtree of the current node is not empty, it will be traversed in recursive order
        if(this.right != null){
            this.right.midOrder();
        }
    }

    /**
     * Binary Tree Postorder Traversal 
     */
    public void postOrder(){
        //If the left subtree of the current node is not empty, it will be traversed recursively
        if (this.left != null){
            this.left.postOrder();
        }
        //If the right subtree of the current node is not empty, it will be traversed recursively
        if (this.right != null){
            this.right.postOrder();
        }
        //Output current node
        System.out.println(this);
    }


    //Binary tree node deletion
    public void delNode(int no){
        //Judge the left node of the current node. If it is not empty and needs to be deleted, delete it directly
        if (this.left != null && this.left.no == no){
            this.left = null;
            return;
        }
        //Judge the right node of the current node. If it is not empty and needs to be deleted, delete it directly
        if (this.right != null && this.right.no == no){
            this.right = null;
            return;
        }

        //If the left node of the current node is not the node to be deleted, the left subtree will be deleted recursively
        if (this.left != null){
            //Recursive deletion
            this.left.delNode(no);
        }
        //If the right node of the current node is not the node to be deleted, the right subtree will be deleted recursively
        if (this.right != null){
            //Recursive deletion
            this.right.delNode(no);
        }

    }
}

🎃 end

Posted by biffjo on Sat, 23 Oct 2021 22:15:29 -0700