C language implementation of binary search tree instance method

  • 2020-04-02 01:53:50
  • OfStack

The following is the detailed flow of the algorithm and its implementation. Since the algorithm is given in pseudocode, some text description is eliminated.




#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORDLEN 16
//Define a node that contains an array of data characters to hold a word in addition to the key value
struct node{
    int key;
    char data[WORDLEN];
    struct node *parent;
    struct node *left;
    struct node *right;
};
typedef struct node * tree;
    
void inorder_tree_walk(tree T)
{
    if(T!=NULL){
        inorder_tree_walk(T->left);
        printf("key:%d   words:%sn",T->key,T->data);
        inorder_tree_walk(T->right);
    }
}

/*============================================
 Search the tree and return containing the keyword k The node 
TREE_SEARCH(x,k) //A recursive version
    if x=NIL or k =key[x]
        then return x
    if k<key[x]
        then return TREE_SEARCH(left[x],k)
        else return TREE_SEARCH(right[x],k)
TREE_SEARCH(x,k) // non A recursive version
    while x!=NIL and k!= key[x]
        do if k<key[x]
            then x < -  left[x]
            else x < -  right[x]
    return x
============================================*/
//A recursive version
struct node* tree_search(tree T,int k)
{
    if(T==NULL || k == T->key)
        return T;
    if(k < T->key)
        return tree_search(T->left,k);
    else 
        return tree_search(T->right,k);
}
// non A recursive version
struct node* tree_search1(tree T,int k)
{
    while(T!=NULL && T->key!=k)
        if(k < T->key)
            T=T->left;
        else 
            T=T->right;
    return T;
}
    
struct node* tree_minimum(tree T)
{
    while(T->left != NULL)
        T=T->left;
    return T;
}

struct node* tree_maxmum(tree T)
{
    while(T->right != NULL)
        T=T->right;
    return T;
}
/*============================================    
 To return the successor of a node 
1 ) if node x If there is a right child, then its successor node is the smallest node in the right subtree. 
2 ) if node x There is no right subtree, and x There is a successor y , y is x The lowest ancestor of 
 and y So is his left son x The ancestors. 
TREE_SUCCESSOR(x)
    if right[x] != NIL
        return TREE_MINIMUM(right[x])
    y=p[x]
    while y!=NIL and x=right[y] //If x=left[y], then the successor to x is y, break out of the while loop and return y
        do x < -  y
           y < -  p[y]
    return y
============================================*/    
struct node * tree_successor(struct node *T)
{
    if(T->right!=NULL)
        return tree_minimum(T->right);
    struct node *y=T->parent;
    while(y!=NULL && T == y->right){
        T=y;
        y=y->parent;
    }
    return y;
}

/*===========================================
 The insert 
 Idea: find the insertion position all the way down from the root node, using the pointer x Trace the path and use the pointer y Point to the x The parent node 
TREE_INSERT(T,z)
    y=NIL
    x=root[T]
    while x!= NIL //Until x is empty, the empty position is the position that needs to be inserted
        do y< -  x
            if key[z]<key[x]
                then x < -  left[x]
                else x < -  right[x]
    p[z]=y
    if y=NIL
        then root[T]=z //The tree T is empty
        else if key[z] < key[y]
            then left[y]=z //Less than y is on the left and more than y is on the right
            else right[y]=z
============================================*/    
void tree_insert(tree *PT,struct node *z)
{
    if(*PT==NULL){//If the tree is empty, return z as the root node
        *PT=z;
        return;
    }
    struct node *y=NULL;
    struct node *x=*PT;
    while(x!=NULL){
        y=x;
        if(z->key < x->key)
            x=x->left;
        else
            x=x->right;
    }
    z->parent=y;
    if(z->key < y->key)
        y->left=z;
    else
        y->right=z;
}
/*===============================================
 Delete operation 
 Delete operations fall into three categories: 
1 ) the node to be deleted z No children, just modify z The child of the parent node is NIL Can be 
2 ) the node to be deleted z If you have only one child, you only need to z This child and z Can be connected to the parent node 
3 ) the node to be deleted z If you have two children, you need to delete them first z In the subsequent y And use it to y Content replacement of z The content of the. 
TREE_DELETE(T,z)
    if left[z]=NIL || right[z]=NIL  //Save the node to be deleted in y
        then y < -  z  
        else y < -  TREE_SUCCESSOR(z)
    if left[y]!=NIL                 //Store y's non-empty children in x
        then X < -  left[y]
        else x < -  right[y]
    if x!=NIL 
        then p[x]=p[y]    //The child of the node to be deleted connects to the parent node of the node to be deleted
    if p[y]=NIL     //If the node to be deleted is the root node
        then root[T] < -  x
        else if y=left[p[y]]//
            then left[p[y]] < -  x
            else right[p[y]] < -  x
    if y!=z  //In the third case, you need to replace the contents of z with the contents of y
        then key[z] < -  key[y]
            copy y's other data to z
    return y
==============================================*/
struct node * tree_delete(tree *PT,struct node *z)
{
    struct node *delnode,*sonnode;
    if(z->left==NULL || z->right == NULL)//With or without children, the node ending z itself is to be deleted
        delnode=z;
    else                                 //If there are two children, the node to be deleted is the successor of z
        delnode=tree_successor(z);
    if(delnode->left!=NULL)
        sonnode=delnode->left;
    else
        sonnode=delnode->right;

    if(sonnode!=NULL)
        sonnode->parent=delnode->parent;
    if(delnode->parent==NULL)
        *PT=sonnode;
    else if(delnode->parent->left==delnode)
        delnode->parent->left=sonnode;
    else
        delnode->parent->right=sonnode;
    if(delnode!=z){
        z->key=delnode->key;
        strcpy(z->data,delnode->data);
    }
    return delnode;
}
//Initialize a tree
tree init_tree(int key)
{    
    struct node * t;
    t=(tree)malloc(sizeof(struct node));
    if(t==NULL)
        return NULL;
    t->key=key;
    t->parent=t->left=t->right=NULL;
    return t;
}
//Release resources
void fini_tree(tree T)
{
    if(T!=NULL){
        fini_tree(T->left);
        fini_tree(T->right);
        printf("free node(%d,%s) nown",T->key,T->data);
        free(T);

    }
}
//The test program
int main()
{
    tree myTree=init_tree(256);
    if(myTree==NULL)
        return 1;
    strcpy(myTree->data,"JJDiaries");
    struct record{
    int key;
    char word[WORDLEN];
    };
    struct record records[]={ {2,"Viidiot"},
                     {4,"linux-code"},
                     {123,"google"},
                     {345,"baidu"},
                     {543,"nsfocus"}
                    };
    int i;
    struct node *tmp;
    for(i=0;i<5;++i){
        tmp=(tree)malloc(sizeof(struct node));
        if(tmp==NULL)
            continue;
        tmp->key=records[i].key;
        strcpy(tmp->data,records[i].word);
        tmp->left=tmp->right=tmp->parent=NULL;
        tree_insert(&myTree,tmp);
    }
    inorder_tree_walk(myTree);
    struct node *del;
    del=tree_delete(&myTree,tree_search(myTree,345));
    printf("Delete node(%d,%s)n",del->key,del->data);
    free(del);
    inorder_tree_walk(myTree);
    fini_tree(myTree);
}

Program running results:
Jjdiaries @ ubuntu > . / search_tree
Key: 2 words: Viidiot
Key: 4 words: Linux - code
Key: 123 words: Google
Key: 256 words: JJDiaries
Key: 345 words: baidu
Key: 543 words: nsfocus
Delete the node (345, baidu)
Key: 2 words: Viidiot
Key: 4 words: Linux - code
Key: 123 words: Google
Key: 256 words: JJDiaries
Key: 543 words: nsfocus
Free node (123, Google) now
Free node (4, Linux - code) now
Free node (2, Viidiot) now
Now, nsfocus free node (543)
Now, JJDiaries free node (256)


Related articles: