C language implements the insertion, deletion and search of binary sort tree (detailed illustration)

1 definition of binary sort tree:

If its left subtree is not empty, the value of all nodes on the left subtree is less than that of its root node

If its right subtree is not empty, the value of all nodes on the right subtree is greater than that of its root node

The left and right subtrees of the root node are binary sort trees

(binary sort tree may degenerate into a linked list, so there is the concept of balanced binary tree; the middle order traversal of binary sort tree is ordered from small to large)

2 binary sort tree structure and node creation function

typedef struct Tree //Binary tree
{
    int data;           //Data domain
    struct Tree *left;  //Left child node pointer
    struct Tree *right; //Right child node pointer
} Tree;
Tree *createBinarySortTreeNode(int data)
{
    Tree *node = (Tree *)malloc(sizeof(Tree));
    node->data = data;
    node->left = NULL;
    node->right = NULL;
    return node;
}

3 node insertion of binary sort tree

Idea: compare the data of the node to be inserted with the data of the root node. If it is less than the data of the root node, insert the left subtree of the root node; If it is greater than the data of the root node, insert the right subtree of the root node;

Inserting a subtree is equivalent to inserting a smaller tree, so it can be implemented recursively until a node without a subtree is found, and the new node is inserted below it to become a leaf node.

void insertBinarySortTreeNode(Tree *dataNode, Tree **root) //The binary sort tree is inserted into the node. Because the root node may change, the secondary pointer is passed
{
    if (*root == NULL || dataNode == NULL)
    {
        *root = dataNode;
        return;
    }
    if (dataNode->data > (*root)->data)//If the inserted node is larger than the data of the original node, the inserted node needs to be placed in the right subtree of root
    {
        if ((*root)->right == NULL)//Find insertion location
        {
            (*root)->right = dataNode;
            return;
        }
        if ((*root)->right)
            insertBinarySortTreeNode(dataNode, &(*root)->right);//Recursively find the insertion position of dataNode
    }
    if (dataNode->data <= (*root)->data)//If the equals sign is removed, it means that nodes with the same data are not inserted
    {
        if ((*root)->left == NULL)//Find insertion location
        {
            (*root)->left = dataNode;
            return;
        }
        if ((*root)->left)
            insertBinarySortTreeNode(dataNode, &(*root)->left); //Recursively find the insertion position of dataNode
    }
}

4. Get the maximum key value node of binary sort tree

  • Idea: since the key values of the nodes of the right subtree are greater than those of the root node of the binary sort tree, you need to start searching from the root node of the right subtree Until the right child node of the last right subtree is found, that is, the node corresponding to the maximum key value. This process can be implemented recursively.
Tree *maxValueOfBinaryTree(Tree *root)
{
    if (root == NULL)//Null pointer judgment
        return NULL;
    Tree *pointer = root;
    while (pointer->right)//After jumping out of the loop, the pointer points to the last right child node
        pointer = pointer->right;
    return pointer;
}

5. Obtaining the minimum key value node of binary sort tree (the idea is the same as above and will not be repeated)

Tree *minValueOfBinaryTree(Tree *root)
{
    if (root == NULL)
        return NULL;
    Tree *pointer = root;
    while (pointer->left)
        pointer = pointer->left;
    return pointer;
}

6 binary sort tree finds the parent node of the specified node

Tree *parentNodeOfBinaryTreeNode(Tree *dataNode, Tree *root) //Gets the parent node of the dataNode node
{
    if (dataNode == NULL || root == NULL || root == dataNode) //Null pointer judgment, and root itself has no parent node
        return NULL;
    Tree *pointer = root;
    Tree *parentNode = pointer;
    while (pointer != NULL && pointer->data != dataNode->data)
    {
        parentNode = pointer;
        if (dataNode->data > pointer->data)
            pointer = pointer->right;
        else
            pointer = pointer->left;
    } //After each cycle, the parentNode is always the parent node of the pointer
    //After the loop jumps out, either the dataNode is found or the pointer is NULL
    if (pointer == NULL)
    {
        printf("node dataNode non-existent\n");
        return NULL;
    }
    return parentNode;
}

7 delete node in binary sort tree

  • 7.1 if the deleted node is a leaf node (no child node), set the deleted node to NULL (the parent node of the deleted node points to NULL); Special case: if the deleted node is the root node, set root to NULL
  • 7.2 if the deleted node has a child node, point the parent node of the deleted node to the child node of the deleted node. Special case: if the deleted node is the root node, it can be considered to delete the head node of the linked list and take the second node as the header.
  • 7.3 if the deleted node has two child nodes, in order to ensure the order of the binary sort tree, it is necessary to find the two nodes closest to the key value of the deleted node. According to the characteristics of the binary tree, these two nodes are located in the rightmost node of the left subtree and the leftmost node of the right subtree of the deleted node. Then point the parent node of the deleted node to any one of them (for example, the rightmost node of the left subtree, hereinafter referred to as the substitute node), and the right pointer of the substitute node points to the right subtree of the deleted node; If the parent node of the substitute node is not the deleted node, the left pointer of the substitute node points to the left subtree of the deleted node, and the parent node of the substitute node points to the left subtree of the substitute node (there is no left subtree when the substitute node is at the rightmost); Special case 1: when the deleted node is root, special case 2: when the parent node of the replacement node is the deleted node, the code analysis can be seen
  • Finally, release the space for deleting nodes

The code is as follows

void deleteBinarySortTreeNode(Tree *deleteNode, Tree **root) //Delete a node in the binary tree
{
    Tree *parentOfDeleteNode = parentNodeOfBinaryTreeNode(deleteNode, *root); //Delete parent node of node
    if (deleteNode == NULL || root == NULL)                                   //Null pointer judgment
        return;
    if (deleteNode != *root && parentOfDeleteNode == NULL) //If the deleted node is not root and parentOfDeleteNode==NULL, it means that the deleted node is not found or the root node of the tree is NULL, so it ends directly;
        return;
    if (deleteNode->left == NULL && deleteNode->right == NULL) // Case: 1 case where the deleted node is a leaf node
    {
        if (*root == deleteNode) //The deleted node is the root node
        {
            *root = NULL;
            return;
        }
        if (parentOfDeleteNode->left == deleteNode)
            parentOfDeleteNode->left = NULL;
        if (parentOfDeleteNode->right == deleteNode)
            parentOfDeleteNode->right = NULL;
    }
    else if (deleteNode->left == NULL || deleteNode->right == NULL) // case: 2 the deleted node has only one of the left subtree or the right subtree
    {
        if (*root == deleteNode)
        {
            if ((*root)->left != NULL) //The deleted node is the root node, and the root node has only the left subtree
                (*root) = (*root)->left;
            else if ((*root)->right != NULL)
                (*root) = (*root)->right; //The deleted node is the root node, and the root node has only the right subtree
        }
        else if (deleteNode->left != NULL) //The deleted node has only the left subtree
        {
            if (parentOfDeleteNode->left == deleteNode)      //The deleted node is the left child node of the parent node, and the deleted node has only the left child tree
                parentOfDeleteNode->left = deleteNode->left; //Point the left of the parent node to the left child node of deleteNode
            if (parentOfDeleteNode->right == deleteNode)
                parentOfDeleteNode->right = deleteNode->left;
        }
        else if (deleteNode->right != NULL)
        {
            if (parentOfDeleteNode->left == deleteNode) //
                parentOfDeleteNode->left = deleteNode->right;
            if (parentOfDeleteNode->right == deleteNode)
                parentOfDeleteNode->right = deleteNode->right;
        }
    }
    else if (deleteNode->left != NULL || deleteNode->right != NULL) // case: 3 deleted nodes have left subtree and right subtree
    {
        Tree *replaceNode = maxValueOfBinaryTree(deleteNode->left);
        //Find the rightmost node of the left subtree of the deleted node (corresponding to the maximum key value of the left subtree) as the substitute node. The key value of the substitute node is adjacent to the key value of the deleted node,
        Tree *parentOfReplaceNode = parentNodeOfBinaryTreeNode(replaceNode, *root); //Gets the parent node of the substitute node
        if (*root == deleteNode)
        {
            parentOfReplaceNode->right = replaceNode->left;
            replaceNode->left = (*root)->left;
            replaceNode->right = (*root)->right;
            (*root) = replaceNode;
        }
        else if (parentOfDeleteNode->left == deleteNode) //The deleted node is the left child of its parent node
        {
            parentOfDeleteNode->left = replaceNode; //The parent node left of the deleted node points to the substitute node
            replaceNode->left = deleteNode->left;
            if (parentOfReplaceNode != deleteNode)
            {
                replaceNode->right = deleteNode->right;
                //The right subtree of the substitute node points to the right subtree of the deleted node (if the parent node of the substitute node is the deleted node, deletenode - > right is the substitute node, resulting in the loss of the following subtree; parentofreplacenode - > right is meaningless)
                parentOfReplaceNode->right = replaceNode->left;
            }
            else if (parentOfReplaceNode == deleteNode)
                replaceNode->right = deleteNode->right->left; //The right subtree of the replacement node points to the left subtree of the replacement node. It is easy to understand from the tree diagram
        }
        else if (parentOfDeleteNode->right == deleteNode) //The deleted node is the right child node of the parent node
        {
            parentOfDeleteNode->right = replaceNode; //Delete the parent node of the node. right points to the node corresponding to the maximum key value of the left subtree
            replaceNode->right = deleteNode->right;
            if (parentOfReplaceNode != deleteNode)
            {
                replaceNode->left = replaceNode->left;
                parentOfReplaceNode->right = replaceNode->left;
            }
            else if (parentOfReplaceNode == deleteNode)
                replaceNode->left = replaceNode->left->left;
        }
    }
    free(deleteNode);
}

8 in order to traverse the code and find the specified node code

Tree *searchTreeNode(Tree *root, int value) //Searches for nodes in a binary sort tree that contain the specified data
{
    if (root == NULL)
        return NULL;
    if (root->data > value)
        return searchTreeNode(root->left, value);
    if (root->data < value)
        return searchTreeNode(root->right, value);
    else
        return root;
}
void inOrderList(Tree *root)//Middle order traversal
{
    if (root == NULL)
        return;
    inOrderList(root->left);
    printf("%d->", root->data);
    inOrderList(root->right);
}

9 function test and operation results

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
    int array[] = {2, 6, 9, 8, 12, 3, 5, 4, 0, -66, 1, -88};
    Tree root = {2, NULL, NULL};
    Tree *pointer = &root;
    for (int i = 1; i < sizeof(array) / sizeof(array[0]); i++)
    {
        Tree *node = createBinarySortTreeNode(array[i]);
        insertBinarySortTreeNode(node, &pointer);//Insert node
    }
    inOrderList(&root); //Order traversal in binary sort tree
    puts("");
    Tree *maxNode = maxValueOfBinaryTree(&root);//Maximum key node lookup
    printf("the maxValueNode:{data:%d left:%p right:%p}\n", maxNode->data, maxNode->left, maxNode->right);
    Tree *minNode = minValueOfBinaryTree(&root);//Minimum key node lookup
    printf("the minValueNode:{data:%d left:%p right:%p}\n", minNode->data, minNode->left, minNode->right);
    Tree *searchNode = searchTreeNode(&root, 6);//Find the specified node
    printf("searchNode->{data:%d left:%p right:%p}\n", searchNode->data, searchNode->left, searchNode->right);
    Tree *parentNode = parentNodeOfBinaryTreeNode(searchNode, &root);//Specifies the parent node lookup for the node
    printf("parentNode->{data:%d left:%p right:%p} searchNode:%p\n", parentNode->data, parentNode->left, parentNode->right, searchNode);
    //If the test deletes the root node, you need to remove the data of the parent node in the uplink printf, because it is NULL and cannot be dereferenced
    Tree *pointer2 = &root;
    deleteBinarySortTreeNode(searchNode, &pointer2);//Delete the specified node
    printf("Delete node searchNode After node:  ");
    inOrderList(pointer2);//Middle order traversal
    return 0;
}

The operation results are as follows:

 

Keywords: C Back-end

Added by mubashir on Thu, 27 Jan 2022 08:41:51 +0200