[data structure] compared with the array linked list, I found that the binary tree is good

preface

If you think the article is helpful, please leave some praise and collection. Pay attention to xiaoleng and read more dry goods learning articles

★ this is Xiao Leng's blog ‡ see the column for good articles on high-quality technology The official account of the individual, sharing some technical articles, and the pit encountered. Current series: data structure series Source code git warehouse Data structure code address Code Git warehouse address

catalogue

Introduction to binary tree

Why do you need a tree data structure?

Concept of binary tree

  1. There are many kinds of trees, and each node can only have two child nodes at most. One form is called binary tree.
  2. The child nodes of binary tree are divided into left node and right node

3. 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, then we call it a full binary tree.

4. If all leaf nodes of the binary tree are in the last layer or the penultimate layer, and the leaf nodes of the last layer are continuous on the left, it is penultimate The leaf nodes of the layer are continuous on the right, which is called complete binary tree

array

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, which is inefficient

Draw the operation diagram:

Linked list

Analysis of chain storage mode

Advantages: to a certain extent, the storage mode of the array is optimized (for example, if you insert a numeric node, you only need to link the inserted node to the linked list,

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)

Operation diagram:

Binary tree

Analysis of tree storage mode

It can improve the efficiency of data storage and reading. For example, using binary sort tree can not only ensure the retrieval speed of data, but also

It can ensure the speed of data insertion, deletion and modification

Case: [7, 3, 10, 1, 5, 9, 12]

Cognitive tree structure

Common terms of tree (understood in combination with schematic diagram):

1) node  

2) Root node  

3) Parent node  

4) Child node  

5) Leaf node (Nodes without child nodes)  6) Weight of node(Node value)  7) route(from root Node finds the route of the node)  8) layer  

6) subtree  

7) Height of tree(Max layers )  
  1. Forest: a forest composed of several sub trees

Description of binary tree traversal

  1. Preorder traversal: first output the parent node, and then traverse the left and right subtrees
  2. Middle 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 finally output the parent node
  4. Summary: see the order of output parent nodes to determine whether it is pre order, middle order or post order

Binary tree traversal application examples (pre order, middle order, post order)

Binary tree traversal code example

 public static void main(String[] args){
     //  Test, first create a binary tree
        BinaryTree binaryTree = new BinaryTree();
        heroNode root = new heroNode(1, "Song Jiang");
        heroNode node1 = new heroNode(2, "Wu Yong");
        heroNode node2 = new heroNode(3, "Lu Junyi");
        heroNode node3 = new heroNode(4, "Lin Chong");
        heroNode node4 = new heroNode(5, "Guan Sheng");
        //Set header node
        binaryTree.setHead(root);
        // Here we fill the binary tree manually, and then we will fill the binary tree recursively
        root.setLeftNode(node1);
        root.setRightNode(node2);
        node2.setRightNode(node3);
        node2.setLeftNode(node4);
        //test
            Preorder traversal
        //binaryTree.PreOrder();
        Middle order traversal
        //System.out.println();
        //binaryTree.InfixOrder();
        Postorder traversal
        //System.out.println();
        //binaryTree.PostOrder();
 }    

class BinaryTree {
    //Determine root node
    private heroNode head;

    public void setHead(heroNode head) {
        this.head = head;
    }

    //   Preorder traversal
    public void PreOrder() {
        if (this.head != null) {
            this.head.PreOrder();
        } else {
            System.out.println("Binary tree has no root node and cannot be traversed");
        }
    }

    //Middle order traversal
    public void InfixOrder() {
        if (this.head != null) {
            this.head.infixOrder();
        } else {
            System.out.println("Binary tree has no root node and cannot be traversed");
        }
    }

    //Subsequent traversal
    public void PostOrder() {
        if (this.head != null) {
            this.head.postOrder();
        } else {
            System.out.println("Binary tree has no root node and cannot be traversed");
        }
    }
}

class heroNode {
    private int id;
    private String name;
    private heroNode leftNode;
    private heroNode rightNode;

    public heroNode getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(heroNode leftNode) {
        this.leftNode = leftNode;
    }

    public heroNode getRightNode() {
        return rightNode;
    }

    public void setRightNode(heroNode rightNode) {
        this.rightNode = rightNode;
    }

    public heroNode(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

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

    }

    //    Preorder traversal
    public void PreOrder() {
        System.out.println(this);
        if (this.getLeftNode() != null) {
            this.leftNode.PreOrder();
        }
        if (this.getRightNode() != null) {
            this.rightNode.PreOrder();
        }
    }

    //    Middle order traversal
    public void infixOrder() {
        if (this.leftNode != null) {
            this.leftNode.infixOrder();
        }
        System.out.println(this);
        if (this.rightNode != null) {
            this.rightNode.infixOrder();
        }
    }

    //   Postorder traversal
    public void postOrder() {
        if (this.leftNode != null) {
            this.leftNode.postOrder();
        }
        if (this.rightNode != null) {
            this.rightNode.postOrder();
        }
        System.out.println(this);
    }
}

Binary tree search idea

  1. Please write the methods of pre order search, middle order search and post order search.
  2. Three search methods are used to find the node with heroNO = 5
  3. And analyze various search methods, and compare how many times

Train of thought diagram

Binary tree lookup code example

In order to facilitate better reading the code, the search code of nodes and tree classes will be specially written, followed by the whole code

class BinatyTree{
    
    //Preorder search
    public heroNode preOrderSearch(int no) {
        if (this.head != null) {
            return this.head.PreOrderSearch(no);
        } else {
            return null;
        }
    }

    //Medium order search
    public heroNode infixOrderSearch(int no) {
        if (this.head != null) {
            return this.head.infixOrderSearch(no);
        } else {
            return null;
        }
    }

    //Sequential search
    public heroNode postOrderSearch(int no) {
        if (this.head != null) {
            return this.head.postOrderSearch(no);
        } else {
            return null;
        }
    }
}
class heroNode{
    
    //Preorder search
    public heroNode preOrderSearch(int no) {
        if (this.head != null) {
            return this.head.PreOrderSearch(no);
        } else {
            return null;
        }
    }

    //Medium order search
    public heroNode infixOrderSearch(int no) {
        if (this.head != null) {
            return this.head.infixOrderSearch(no);
        } else {
            return null;
        }
    }

    //Sequential search
    public heroNode postOrderSearch(int no) {
        if (this.head != null) {
            return this.head.postOrderSearch(no);
        } else {
            return null;
        }
    }

}

Binary tree - delete node

  • If the deleted node is a leaf node, delete the node
  • If the deleted node is a non leaf node, the subtree is deleted
  • Test, delete No. 5 leaf node and No. 3 subtree

Train of thought analysis

Binary tree, traversal, search, delete the whole code

package com.hyc.DataStructure.tree;

/**
 * @projectName: DataStructure
 * @package: com.hyc.DataStructure.tree
 * @className: BinaryTreeDemo
 * @author: Cold Huanyuan doorwatcher
 * @description: TODO
 * @date: 2022/2/3 16:47
 * @version: 1.0
 */
public class BinaryTreeDemo {
    public static void main(String[] args) {
        //  Test, first create a binary tree
        BinaryTree binaryTree = new BinaryTree();
        heroNode root = new heroNode(1, "Song Jiang");
        heroNode node1 = new heroNode(2, "Wu Yong");
        heroNode node2 = new heroNode(3, "Lu Junyi");
        heroNode node3 = new heroNode(4, "Lin Chong");
        heroNode node4 = new heroNode(5, "Guan Sheng");
        //Set header node
        binaryTree.setHead(root);
        // Here we fill the binary tree manually, and then we will fill the binary tree recursively
        root.setLeftNode(node1);
        root.setRightNode(node2);
        node2.setRightNode(node3);
        node2.setLeftNode(node4);
        //test
            Preorder traversal
        //binaryTree.PreOrder();
        Middle order traversal
        //System.out.println();
        //binaryTree.InfixOrder();
        Postorder traversal
        //System.out.println();
        //binaryTree.PostOrder();


        //System.out.println("front, middle and back search");
        //System.out.println("start pre order search");
        //heroNode resNode = binaryTree.preOrderSearch(5);
        //if (resNode != null) {
        //    System.out.printf("found node is no = >% D, name = >% s", resnode. Getid(), resnode getName());
        //} else {
        //    System.out.println("search failed");
        //}
        //System.out.println("start middle order search");
        //heroNode resNode = binaryTree.infixOrderSearch(5);
        //if (resNode != null) {
        //    System.out.printf("found node is no = >% D, name = >% s", resnode. Getid(), resnode getName());
        //} else {
        //    System.out.println("search failed");
        //}
        //System.out.println("start post order search");
        //heroNode resNode = binaryTree.postOrderSearch(5);
        //if (resNode != null) {
        //    System.out.printf("found node is no = >% D, name = >% s", resnode. Getid(), resnode getName());
        //} else {
        //    System.out.println("search failed");
        //}

        //    Delete test
        System.out.println("Before deletion");
        binaryTree.PreOrder();
        System.out.println("After deletion");
        binaryTree.deleteNode(5);
        binaryTree.PreOrder();

    }
}


class BinaryTree {
    //Determine root node
    private heroNode head;

    public void setHead(heroNode head) {
        this.head = head;
    }

    //   Preorder traversal
    public void PreOrder() {
        if (this.head != null) {
            this.head.PreOrder();
        } else {
            System.out.println("Binary tree has no root node and cannot be traversed");
        }
    }

    //Middle order traversal
    public void InfixOrder() {
        if (this.head != null) {
            this.head.infixOrder();
        } else {
            System.out.println("Binary tree has no root node and cannot be traversed");
        }
    }

    //Subsequent traversal
    public void PostOrder() {
        if (this.head != null) {
            this.head.postOrder();
        } else {
            System.out.println("Binary tree has no root node and cannot be traversed");
        }
    }

    //Preorder search
    public heroNode preOrderSearch(int no) {
        if (this.head != null) {
            return this.head.PreOrderSearch(no);
        } else {
            return null;
        }
    }

    //Medium order search
    public heroNode infixOrderSearch(int no) {
        if (this.head != null) {
            return this.head.infixOrderSearch(no);
        } else {
            return null;
        }
    }

    //Sequential search
    public heroNode postOrderSearch(int no) {
        if (this.head != null) {
            return this.head.postOrderSearch(no);
        } else {
            return null;
        }
    }


    //    Delete node
    public void deleteNode(int no) {
        if (head != null) {
            if (head.getId() == no) {
                head = null;
                return;
            } else {
                head.deleteNode(no);
            }
        } else {
            System.out.println("Empty tree,Cannot delete");
        }
    }
}

class heroNode {
    private int id;
    private String name;
    private heroNode leftNode;
    private heroNode rightNode;

    public heroNode getLeftNode() {
        return leftNode;
    }

    public void setLeftNode(heroNode leftNode) {
        this.leftNode = leftNode;
    }

    public heroNode getRightNode() {
        return rightNode;
    }

    public void setRightNode(heroNode rightNode) {
        this.rightNode = rightNode;
    }

    public heroNode(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

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

    }

    //    Preorder traversal
    public void PreOrder() {
        System.out.println(this);
        if (this.getLeftNode() != null) {
            this.leftNode.PreOrder();
        }
        if (this.getRightNode() != null) {
            this.rightNode.PreOrder();
        }
    }

    //    Middle order traversal
    public void infixOrder() {
        if (this.leftNode != null) {
            this.leftNode.infixOrder();
        }
        System.out.println(this);
        if (this.rightNode != null) {
            this.rightNode.infixOrder();
        }
    }

    //   Postorder traversal
    public void postOrder() {
        if (this.leftNode != null) {
            this.leftNode.postOrder();
        }
        if (this.rightNode != null) {
            this.rightNode.postOrder();
        }
        System.out.println(this);
    }

    //   Preorder search
    public heroNode PreOrderSearch(int no) {
        System.out.println("Preorder search");
        //Compare whether the no of the current node is what we want to search
        if (this.id == no) {
            return this;
        }
        //Node to return
        heroNode resNode = null;
        //  Judge whether the node on the left is empty. If it is not empty, recursive preamble search is performed
        //    If found, return the found node
        if (this.leftNode != null) {
            resNode = this.leftNode.PreOrderSearch(no);
        }
        //If it is not null, it means that if it is found on the left, it can be returned directly
        if (resNode != null) {
            return resNode;
        }
        //  Judge whether the node on the right is empty. If it is not empty, recursive preamble search is performed
        //    If found, return the found node
        if (this.rightNode != null) {
            resNode = this.rightNode.PreOrderSearch(no);
        }
        return resNode;
    }

    //   Medium order search
    public heroNode infixOrderSearch(int no) {

        //Node to return
        heroNode resNode = null;
        //  Judge whether the left node is empty. If it is not empty, search in recursive order
        //    If found, return the found node
        if (this.leftNode != null) {
            resNode = this.leftNode.infixOrderSearch(no);
        }
        //If it is not null, it means that if it is found on the left, it can be returned directly
        if (resNode != null) {
            return resNode;
        }
        //Compare whether the no of the current node is what we want to search
        System.out.println("Medium order search");
        if (this.id == no) {
            return this;
        }
        //  Judge whether the node on the right is empty. If it is not empty, search in recursive order
        //    If the node is found, it will return
        if (this.rightNode != null) {
            resNode = this.rightNode.infixOrderSearch(no);
        }
        return resNode;
    }

    //   Sequential search
    public heroNode postOrderSearch(int no) {

        //Node to return
        heroNode resNode = null;
        //  Judge whether the node on the left is empty. If it is not empty, it will be searched recursively
        //    If found, return the found node
        if (this.leftNode != null) {
            resNode = this.leftNode.postOrderSearch(no);
        }
        //If it is not null, it means that if it is found on the left, it can be returned directly
        if (resNode != null) {
            return resNode;
        }
        //  Judge whether the node on the right is empty. If it is not empty, it will be searched recursively
        //    If found, return the found node
        if (this.rightNode != null) {
            resNode = this.rightNode.postOrderSearch(no);
        }
        //If it is not null, it means that if it is found on the right, it can be returned directly
        if (resNode != null) {
            return resNode;
        }
        System.out.println("Sequential search");
        //If the left and right subtrees are not found, then compare whether the no of the current node is what we want to search
        if (this.id == no) {
            return this;
        }
        return resNode;
    }


    //    delete 
    public void deleteNode(int no) {
        //    Traverse to the left. If the left subtree is a little, set the left subtree empty. If not, traverse the right
        if (this.leftNode != null && this.leftNode.id == no) {
            this.leftNode = null;
            return;
        }
        //    Traverse to the right. If the right subtree is a little, set the left subtree empty. If there is no ready left or right, it should be deleted recursively
        if (this.rightNode != null && this.rightNode.id == no) {
            this.rightNode = null;
            return;
        }
        //    If the above two steps are unsuccessful, let's delete recursively to the left first
        if (this.leftNode != null) {
            this.leftNode.deleteNode(no);
        }

        //    If the recursive deletion of the left subtree is not successful, the right subtree will be deleted recursively
        if (this.rightNode != null) {
            this.rightNode.deleteNode(no);
        }
    }

}

Added by voxanBoxer on Wed, 23 Feb 2022 08:40:53 +0200