[C + +] [binary tree] [binary search tree] build a binary search tree class.

1, Key analysis

1. Insert node

Inserting a node is relatively simple. You only need to judge the key value, replace the corresponding key value, or create a new key value.

 // Insert the node (key, value) into the binary search tree with node as the root, and use the recursive algorithm
    // Returns the root of the binary search tree after inserting a new node
    Node* insert(Node *node, Key key, Value value){

        if( node == NULL ){
            count ++;
            return new Node(key, value);
        }

        if( key == node->key )
            node->value = value;
        else if( key < node->key )
            node->left = insert( node->left , key, value);
        else    // key > node->key
            node->right = insert( node->right, key, value);

        return node;
    }

2. Delete node

2.1. Delete the latest value

First, the minimum value of BST will only have a right subtree. Similarly, the maximum value of BST will only have left subtree.

Delete minimum value: just find the minimum value to the left, link its right subtree to the parent node of the minimum value, and then delete the minimum value.

Delete maximum value: just find the maximum value to the right, link its left sub tree to the parent node of the maximum value, and then delete the maximum value.

Similarly, if the right subtree is empty, there is no problem connecting it.

    // Delete the smallest node in the binary search tree with node as the root, and use the recursive algorithm
    // Returns the root of the new binary search tree after deleting the node
    Node* removeMin(Node* node){

        if( node->left == NULL ){

            Node* rightNode = node->right;
            delete node;
            count --;
            return rightNode;
        }

        node->left = removeMin(node->left);
        return node;
    }

    // Delete the largest node in the binary search tree with node as the root, and use the recursive algorithm
    // Returns the root of the new binary search tree after deleting the node
    Node* removeMax(Node* node){

        if( node->right == NULL ){

            Node* leftNode = node->left;
            delete node;
            count --;
            return leftNode;
        }

        node->right = removeMax(node->right);
        return node;
    }

2.2. Delete general nodes

Deleting a general node is divided into several categories

  1. The node to be deleted has only the right child.
  2. Only the left child is the node to be deleted.
  3. There are children on both sides of the deleted node.

For the above three cases, only the last one is slightly complicated.

  1. Link its right child to its parent node and delete the node
  2. Link its left child to its parent node and delete the node
  3. Change the successor node of this node to the current node and delete the location of the original successor node. (the successor node replaces the node position)

The successor node is the smallest node in the right subtree of the node.

Of course, this operation can also be completed with the preamble node.

The preceding node is the largest node in the left subtree of this node (see node 53 in the figure below).


    // Delete the node with the key value as the key in the binary search tree with node as the root, and use the recursive algorithm
    // Returns the root of the new binary search tree after deleting the node
    Node* remove(Node* node, Key key){

        if( node == NULL )
            return NULL;

        if( key < node->key ){
            node->left = remove( node->left , key );
            return node;
        }
        else if( key > node->key ){
            node->right = remove( node->right, key );
            return node;
        }
        else{   // key == node->key

            if( node->left == NULL ){
                Node *rightNode = node->right;
                delete node;
                count --;
                return rightNode;
            }

            if( node->right == NULL ){
                Node *leftNode = node->left;
                delete node;
                count--;
                return leftNode;
            }

            // node->left != NULL && node->right != NULL
            Node *successor = new Node(minimum(node->right));
            count ++;

            successor->right = removeMin(node->right);
            successor->left = node->left;

            delete node;
            count --;

            return successor;
        }
    }

3. Destructor

Destructor requires the idea of post order traversal.

That is, to delete the current node, the left and right subtrees must be deleted first, otherwise the whole tree cannot be deleted.

The following code is actually a recursive destructor of post order traversal.

    // Release all nodes of the binary search tree with node as the root
    // Recursive algorithm with subsequent traversal
    void destroy(Node* node){

        if( node != NULL ){
            destroy( node->left );
            destroy( node->right );

            delete node;
            count --;
        }
    }

2, Complete BST class

The complete code is taken from Mr. bobo's github, and there is a path at the end of the text.

// Binary search tree
template <typename Key, typename Value>
class BST{

private:
    // The nodes in the tree are private structures, and the outside world does not need to know the specific implementation of binary search tree nodes
    struct Node{
        Key key;
        Value value;
        Node *left;
        Node *right;

        Node(Key key, Value value){
            this->key = key;
            this->value = value;
            this->left = this->right = NULL;
        }

        Node(Node *node){
            this->key = node->key;
            this->value = node->value;
            this->left = node->left;
            this->right = node->right;
        }
    };

    Node *root; // Root node
    int count;  // Number of nodes in the tree

public:
    // Constructor, which constructs an empty binary search tree by default
    BST(){
        root = NULL;
        count = 0;
    }

    // Destructor to release all space of binary search tree
    ~BST(){
        destroy( root );
    }

    // Returns the number of nodes in the binary search tree
    int size(){
        return count;
    }

    // Returns whether the binary search tree is empty
    bool isEmpty(){
        return count == 0;
    }

    // Insert a new (key, value) data pair into the binary search tree
    void insert(Key key, Value value){
        root = insert(root, key, value);
    }

    // Check whether the key exists in the binary search tree
    bool contain(Key key){
        return contain(root, key);
    }

    // Search the value corresponding to the key in the binary search tree. If this value does not exist, NULL is returned
    Value* search(Key key){
        return search( root , key );
    }

    // Preorder traversal of binary search tree
    void preOrder(){
        preOrder(root);
    }

    // Middle order traversal of binary search tree
    void inOrder(){
        inOrder(root);
    }

    // Post order traversal of binary search tree
    void postOrder(){
        postOrder(root);
    }

    // Sequence traversal of binary search tree
    void levelOrder(){

        queue<Node*> q;
        q.push(root);
        while( !q.empty() ){

            Node *node = q.front();
            q.pop();

            cout<<node->key<<endl;

            if( node->left )
                q.push( node->left );
            if( node->right )
                q.push( node->right );
        }
    }

    // Find the minimum key value of binary search tree
    Key minimum(){
        assert( count != 0 );
        Node* minNode = minimum( root );
        return minNode->key;
    }

    // Find the maximum key value of the binary search tree
    Key maximum(){
        assert( count != 0 );
        Node* maxNode = maximum(root);
        return maxNode->key;
    }

    // Delete the node with the minimum value from the binary search tree
    void removeMin(){
        if( root )
            root = removeMin( root );
    }

    // Delete the node with the maximum value from the binary search tree
    void removeMax(){
        if( root )
            root = removeMax( root );
    }

    // Delete key from search tree
    void remove(Key key){
        root = remove(root, key);
    }

private:
    // Insert the node (key, value) into the binary search tree with node as the root, and use the recursive algorithm
    // Returns the root of the binary search tree after inserting a new node
    Node* insert(Node *node, Key key, Value value){

        if( node == NULL ){
            count ++;
            return new Node(key, value);
        }

        if( key == node->key )
            node->value = value;
        else if( key < node->key )
            node->left = insert( node->left , key, value);
        else    // key > node->key
            node->right = insert( node->right, key, value);

        return node;
    }

    // Check whether the binary search tree with node as the root contains nodes with key value, and use recursive algorithm
    bool contain(Node* node, Key key){

        if( node == NULL )
            return false;

        if( key == node->key )
            return true;
        else if( key < node->key )
            return contain( node->left , key );
        else // key > node->key
            return contain( node->right , key );
    }

    // Find the value corresponding to the key in the binary search tree with node as the root, and use the recursive algorithm
    // If value does not exist, NULL is returned
    Value* search(Node* node, Key key){

        if( node == NULL )
            return NULL;

        if( key == node->key )
            return &(node->value);
        else if( key < node->key )
            return search( node->left , key );
        else // key > node->key
            return search( node->right, key );
    }

    // The binary search tree with node as the root is traversed in advance, and the recursive algorithm
    void preOrder(Node* node){

        if( node != NULL ){
            cout<<node->key<<endl;
            preOrder(node->left);
            preOrder(node->right);
        }
    }

    // The binary search tree with node as the root is traversed in middle order, and the recursive algorithm
    void inOrder(Node* node){

        if( node != NULL ){
            inOrder(node->left);
            cout<<node->key<<endl;
            inOrder(node->right);
        }
    }

    // The binary search tree with node as the root is traversed in order, and the recursive algorithm is used
    void postOrder(Node* node){

        if( node != NULL ){
            postOrder(node->left);
            postOrder(node->right);
            cout<<node->key<<endl;
        }
    }

    // Release all nodes of the binary search tree with node as the root
    // Recursive algorithm with subsequent traversal
    void destroy(Node* node){

        if( node != NULL ){
            destroy( node->left );
            destroy( node->right );

            delete node;
            count --;
        }
    }

    // Returns the node where the minimum key value of the binary search tree with node as the root is located, and the recursive algorithm
    Node* minimum(Node* node){
        if( node->left == NULL )
            return node;

        return minimum(node->left);
    }

    // Returns the node where the maximum key value of the binary search tree with node as the root is located, and the recursive algorithm
    Node* maximum(Node* node){
        if( node->right == NULL )
            return node;

        return maximum(node->right);
    }

    // Delete the smallest node in the binary search tree with node as the root, and use the recursive algorithm
    // Returns the root of the new binary search tree after deleting the node
    Node* removeMin(Node* node){

        if( node->left == NULL ){

            Node* rightNode = node->right;
            delete node;
            count --;
            return rightNode;
        }

        node->left = removeMin(node->left);
        return node;
    }

    // Delete the largest node in the binary search tree with node as the root, and use the recursive algorithm
    // Returns the root of the new binary search tree after deleting the node
    Node* removeMax(Node* node){

        if( node->right == NULL ){

            Node* leftNode = node->left;
            delete node;
            count --;
            return leftNode;
        }

        node->right = removeMax(node->right);
        return node;
    }

    // Delete the node with the key value as the key in the binary search tree with node as the root, and use the recursive algorithm
    // Returns the root of the new binary search tree after deleting the node
    Node* remove(Node* node, Key key){

        if( node == NULL )
            return NULL;

        if( key < node->key ){
            node->left = remove( node->left , key );
            return node;
        }
        else if( key > node->key ){
            node->right = remove( node->right, key );
            return node;
        }
        else{   // key == node->key

            if( node->left == NULL ){
                Node *rightNode = node->right;
                delete node;
                count --;
                return rightNode;
            }

            if( node->right == NULL ){
                Node *leftNode = node->left;
                delete node;
                count--;
                return leftNode;
            }

            // node->left != NULL && node->right != NULL
            Node *successor = new Node(minimum(node->right));
            count ++;

            successor->right = removeMin(node->right);
            successor->left = node->left;

            delete node;
            count --;

            return successor;
        }
    }
};

reference resources

Design of template class and template function

Mr. bobo github

Keywords: C++ Algorithm data structure Binary tree

Added by dietkinnie on Tue, 01 Feb 2022 21:46:07 +0200