Terms:

A Binary Tree is a special type of Tree in which each node has at most two children. The two children are called left children and the other right children

A Binary Search Tree is a Binary Tree in which, for each node x, the values of all descendants of the left subtree are always less than the value of X, and the values of all descendants of the right subtree are always greater than the value of X

A binary search tree

1. Basic implementation:

In general, BST records data as key-value pairs. For simplicity, this article uses string as the type of the key and Value as the type of the Value (Value is a generic type specified when the tree is created). If you’re interested, look at Algorithms, Fourth Edition.

public class BST<Value> {
    private Node root;
    
    private class Node{
        private String key;
        private Value value;
        private Node left;
        private Node right;

        Node(String key,Value value){this.key=key;this.value=value;}
    }
    /* For some methods of binary search tree, see below */
    // Add a node
    public void add(String key,Value value){}

    // Get values based on keys
    public Value get(String key){return 0; }// Get the node with the smallest key
    public Node min(a){return null; }// Get the node with the largest key
    public Node max(a){return null; }// Delete a node
    public void delete(String key){}

    // Middle order traversal of binary tree
    public Iterable<String> inorderTraverse(a){return null;}
}
Copy the code

Select * from key;

Find records by key. If the tree contains the key, the lookup hit, returns the value of the key; If not, the search is not hit and null is returned

// Get values based on keys
public Value get(String key){
    return get(root,key);
}

private Value get(Node x,String key){
    // Find the key in the tree with node X as the root
    Return the value of the key if it can be found, or null if it cannot be found
    if(x==null) return null;                	    // If the current node is null, null is returned

    int cmp=key.compareTo(x.key);           	    // Compare the key of the current node with that of the node to be found
    if(cmp>0) 		return get(x.right,key);    // Continue the search in the right subtree of the current node
    else if(cmp<0) 	return get(x.left,key);     // Continue the search in the left subtree of the current node
    else 		return x.value;             // If the two keys are equal, the search is hit
}
Copy the code

Insert key pair:

Give a key-value pair. If the key is not in the tree, create a new node and hang it on the empty link at the end of the search. If the key exists in the tree, the corresponding value is updated

// Insert a new node
public void add(String key,Value value){
    root=add(root,key,value);
}

private Node add(Node x,String key,Value value){
    // Insert node in tree with x node as root
    if(x==null) return new Node(key,value);     	// if x is empty, the leaf node of the tree has been reached
    												// Create a new key node and hang it on an empty link

    int cmp=key.compareTo(x.key);               	// Compare the node to be inserted with the key of node X
    if(cmp>0)       x.right=add(x.right,key,value);     // Insert nodes in the right subtree of x
    else if(cmp<0)  x.left=add(x.left,key,value);       // Insert a node in the left subtree of x
    else            x.value=value;              	// The tree already has a node corresponding to the key
    return x;                                   	// Return a reference to node x;
}
Copy the code

Obtain the node with the smallest key:

If the left link of the root node is empty, the smallest node in the tree is the root node

If the left link of the root node is not empty, then the smallest node in the left subtree of the root node is the smallest node in the whole tree

So we can recursively find the smallest node

The algorithm for obtaining the maximum node is similar, except for the right subtree of the recursive node

// Get the node with the smallest key
public Node min(a){
    return min(root);
}

private Node min(Node x){
    if(x.left==null) return x;
    return min(x.left);
}
Copy the code

Delete the node with the smallest key:

// Delete the node with the smallest key
public void deleteMin(a){
    if(root==null) return;
    root=deleteMin(root);
}

private Node deleteMin(Node x){
    if(x.left==null) x=x.right;		       // If the left child of x is empty, x is the smallest node to be deleted
    						// Assign the x reference (the left link of the parent node of X) to the right child node of X
    						// The original node is garbage collected because there is no reference to it
    else x.left=deleteMin(x.left);
    return x;
}
Copy the code

6. Delete any node:

The algorithm for deleting nodes in a binary tree based on keys is complex, and the basic steps are as follows:

  1. Find the node you want to delete and point to it using the temporary variable t
  2. Find the smallest node in the right subtree of node T and point to that node using the temporary variable x
  3. Use the deleteMin method to delete the smallest node in the t right subtree and restore the right subtree
  4. The left link of x goes to the left subtree of T, and the right link of x goes to the right subtree of T
  5. Connect x to the parent of T
// Delete a node
public void delete(String key){
    root=delete(root,key);
}

private Node delete(Node x,String key){

    if(x==null) return null;                    // The node whose key is key is not found
    int cmp=key.compareTo(x.key);
    if(cmp>0) x.right=delete(x.right,key);      // Remove the node from the left node of x
    else if(cmp<0) x.left=delete(x.left,key);   // Remove the node from the right node of x
    else{
        if(x.right==null) return x.left;        
        if(x.left==null) return x.right;
        Node t=x;
        x=min(t.right);
        x.right=deleteMin(t.right);				// Delete the smallest node in the right subtree of t and restore the right subtree
        x.left=t.left;
    }
    return x;
}
Copy the code

7. Perform middle-order traversal on the binary search tree

A middle-order traversal of a binary lookup tree yields a collection of nodes ordered by key

Code that iterates recursively is not complex

// Middle order traversal of binary tree
public List<Node> inorderTraverse(a){
    List<Node> list=new ArrayList<>();
    inorderTraverse(root,list);
    return list;
}

private void inorderTraverse(Node x,List<Node> list){
    if(x==null) return;
    inorderTraverse(x.left,list);
    list.add(x);
    inorderTraverse(x.right,list);
}
Copy the code

8. Print the binary lookup tree in the console

public void print(a){
    System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
    print(root,0);
    System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
}

private void print(Node x,int floor){
    if(x==null) return ;
    print(x.left,floor+1);
    for (int i = 0; i < floor; i++) {
        System.out.print("--");
    }
    System.out.println(x.key+""+x.value);
    print(x.right,floor+1);
}
Copy the code

Test cases

In the example, the key is of type String and the value is of type Integer. The test case accepts adding data on the console in the form of $add String. String is the key, and the corresponding value is the order in which the strings are added, $del string for delete, $show for print, and $exit for exit

public static void main(String[] args) {
    BST<Integer> sibst = new BST<>();

    int i=1;
    String str;
    boolean flag=true;
    Scanner in = new Scanner(System.in);
    String[] words;

    while(flag){
        str=in.nextLine();
        if(str.equals("")) continue;
        words = str.split("");
        switch (words[0]) {case "$exit": {
                flag=false;
                break;
            }
            case "$add":{
                sibst.add(words[1],i++);
                break;
            }
            case "$del":{
                sibst.delete(words[1]);
                break;
            }
            case "$show":{
                sibst.print();
                break;
            }
            default:{
                System.out.println("Error command"); }}}}Copy the code

10. Complete code

BST.java

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class BST<Value> {

    private Node root;

    private class Node{
        private String key;
        private Value value;
        private Node left;
        private Node right;

        Node(String key,Value value){
            this.key=key;
            this.value=value; }}// Add a node
    public void add(String key,Value value){
        root=add(root,key,value);
    }

    public Node add(Node x,String key,Value value){
        // Insert node in tree with x node as root
        if(x==null) return new Node(key,value);         // if x is empty, the leaf node of the tree has been reached
                                                        // Create a new key node and hang it on an empty link

        int cmp=key.compareTo(x.key);                   // Compare the node to be inserted with the key of node X
        if(cmp>0)       x.right=add(x.right,key,value); // Insert nodes in the right subtree of x
        else if(cmp<0)  x.left=add(x.left,key,value);   // Insert a node in the left subtree of x
        else            x.value=value;                  // The tree already has a node corresponding to the key
        return x;                                       // Update node x;
    }

    // Get values based on keys
    public Value get(String key){
        return get(root,key);
    }

    private Value get(Node x,String key){
        // Find the key in the tree with node X as the root
        Return the value of the key if it can be found, or null if it cannot be found
        if(x==null) return null;                // If the current node is null, null is returned

        int cmp=key.compareTo(x.key);           // Compare the key of the current node with that of the node to be found
        if(cmp>0) return get(x.right,key);      // Continue the search in the right subtree of the current node
        else if(cmp<0) return get(x.left,key);  // Continue the search in the right subtree of the current node
        else return x.value;                    // If the two keys are equal, the search is hit
    }

    // Get the node with the smallest key
    public Node min(a){
        return min(root);
    }

    private Node min(Node x){
        if(x.left==null) return x;
        return min(x.left);
    }

    // Delete the node with the smallest key
    public void deleteMin(a){
        if(root==null) return;
        root=deleteMin(root);
    }

    private Node deleteMin(Node x){
        if(x.left==null) x=x.right;
        else x.left=deleteMin(x.left);
        return x;
    }

    // Get the node with the largest key
    public Node max(a){
        return null;
    }

    // Delete a node
    public void delete(String key){
        root=delete(root,key);
    }

    private Node delete(Node x,String key){

        if(x==null) return null;                    // The node whose key is key is not found
        int cmp=key.compareTo(x.key);
        if(cmp>0) x.right=delete(x.right,key);      // Remove the node from the left node of x
        else if(cmp<0) x.left=delete(x.left,key);   // Remove the node from the right node of x
        else{
            if(x.right==null) return x.left;
            if(x.left==null) return x.right;
            Node t=x;
            x=min(t.right);
            x.right=deleteMin(t.right);
            x.left=t.left;
        }
        return x;
    }

    // Middle order traversal of binary tree
    public List<Node> inorderTraverse(a){

        List<Node> list=new ArrayList<>();
        inorderTraverse(root,list);
        return list;
    }

    private void inorderTraverse(Node x,List<Node> list){
        if(x==null) return;
        inorderTraverse(x.left,list);
        list.add(x);
        inorderTraverse(x.right,list);
    }

    public void print(a){
        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
        print(root,0);
        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
    }

    private void print(Node x,int floor){
        if(x==null) return ;
        print(x.left,floor+1);

        for (int i = 0; i < floor; i++) {
            System.out.print("--");
        }
        System.out.println(x.key+""+x.value);

        print(x.right,floor+1);
    }

    public static void main(String[] args) {
        BST<Integer> sibst = new BST<>();

        int i=0;
        String str;
        boolean flag=true;
        Scanner in = new Scanner(System.in);
        String[] words;

        while(flag){
            str=in.nextLine();
            if(str.equals("")) continue;
            words = str.split("");
            switch (words[0]) {case "$exit": {
                    flag=false;
                    break;
                }
                case "$add":{
                    sibst.add(words[1],i++);
                    break;
                }
                case "$del":{
                    sibst.delete(words[1]);
                    break;
                }
                case "$show":{
                    sibst.print();
                    break;
                }
                default:{
                    System.out.println("Error command");
                }
            }
        }
    }
}
Copy the code