简体   繁体   中英

Binary Search Tree C implementation

I recently wrote a fairly simple piece of code attempting to implement a Binary Search Tree in C with insertion, search, deletion and display operations. Unfortunately, the code does not seem to work.

#include <stdio.h>
#include <stdlib.h>

struct TreeNode {
    int data;
    struct TreeNode *leftChildNode;
    struct TreeNode *rightChildNode;
};

typedef struct TreeNode node;
node *rootNode = NULL;

void insertNode(int i, node *n) {
    if(n == NULL) {
        n = (node*)malloc(sizeof(node));
        n->leftChildNode = NULL;
        n->rightChildNode = NULL;
        n->data = i;
    }
    else 
    if(n->data == i)
        printf("\nThis value already exists in the tree!");
    else
    if(i > n->data)
        insertNode(i, n->rightChildNode);
    else
        insertNode(i, n->leftChildNode);
    }

void searchNode(int i, node *n) {
    if(n == NULL)
        printf("\nValue does not exist in tree!");
    else
    if(n->data == i)
        printf("\nValue found!");
    else
    if(i > n->data)
        searchNode(i, n->rightChildNode);
    else
        searchNode(i, n->leftChildNode);
    }

void deleteNode(int i, node *n) {
    if(n == NULL)
        printf("\nValue does not exist in tree!");
    else
    if(n->data == i) {
        if(n->leftChildNode == NULL)
            n = n->rightChildNode;
        else
        if(n->rightChildNode == NULL)
            n = n->leftChildNode;
        else {
            node *temp = n->rightChildNode;
            while(temp->leftChildNode != NULL)
                temp = temp->leftChildNode;
            n = temp;
        }
    }
    else
    if(i > n->data)
        deleteNode(i, n->rightChildNode);
    else
        deleteNode(i, n->leftChildNode);
    }

void displayPreOrder(node *n) {
    if(n != NULL) {
        printf("%d ", n->data);
        displayPreOrder(n->leftChildNode);
        displayPreOrder(n->rightChildNode);
    }
}

void displayPostOrder(node *n) {
    if(n != NULL) {
        displayPostOrder(n->leftChildNode);
        displayPostOrder(n->rightChildNode);
        printf("%d ", n->data);
    }
}

void displayInOrder(node *n) {
    if(n != NULL) {
        displayInOrder(n->leftChildNode);
        printf("%d ", n->data);
        displayInOrder(n->rightChildNode);
    }
}

int main(void) {
    int ch, num, num1;
    do {
        printf("\nSelect a choice from the menu below.");
        printf("\n1. Insert a node.");
        printf("\n2. Search for a node.");
        printf("\n3. Delete a node.");
        printf("\n4. Display the Binary Search Tree.");
        printf("\nChoice: ");
        scanf("%d", &ch);
        switch(ch) {
            case 1: printf("\nEnter an element: ");
                    scanf("%d", &num);
                    //printf("YESYES");
                    insertNode(num, rootNode);
                    break;

            case 2: printf("\nEnter the element to be searched for: ");
                    scanf("%d", &num);
                    searchNode(num, rootNode);
                    break;

            case 3: printf("\nEnter the element to be deleted: ");
                    scanf("%d", &num);
                    deleteNode(num, rootNode);
                    break;

            case 4: printf("\nSelect an order for the elements to be display in.");
                    printf("\n1. Pre-order.");
                    printf("\n2. Post-order.");
                    printf("\n3. In-order.");
                    printf("\nChoice: ");
                    scanf("%d", &num1);
                    switch(num1) {
                        case 1: printf("\nPre-order Display: ");
                                displayPreOrder(rootNode);
                                break;

                        case 2: printf("\nPost-order Display: ");
                                displayPostOrder(rootNode);
                                break;

                        case 3: printf("\nIn-order Display: ");
                                displayInOrder(rootNode);
                                break;

                        default: exit(0);
                    }
                    break;

            default: exit(0);
            }
        //printf("%d", rootNode->data);
        printf("\nIf you want to return to the menu, press 1.");
        printf("\nChoice: ");
        scanf("%d", &num);
    } while(num == 1);

    return 0;
}

In fact, notice the commented line printf("%d", rootNode->data); just before the do-while block in main() ends. If I uncomment this line, compile the program and run it, the program throws a segmentation fault. Could anyone tell me why this error is occurring and why the code as a whole isn't running? Thanks in advance.

You have a misconception about the way C handles arguments. In C, all arguments are passed by value, including pointers. When you reassign a pointer inside of a function you are reassigning a copy of that pointer.

For instance:

void f ( int *p );

int *p;

f(p);

The address ( &p ) of the pointer is different in the function. They both point to the same location (have the same value ), but each has a different address . When you assign the pointer to the return value of malloc , it is only assigning the function local copy of that pointer.

One way to fix this is to introduce another level of indirection, and pass the address of the pointer: void insertNode(int i, node **n) , which you can call like insertNode(0, &n) . When you want to change it to something else, dereference it once and then assign: *p = malloc(sizeof(node)) .

Another solution is to have the function return the pointer and assign it in the calling code: return malloc(sizeof(node)) . (Note: You would actually return it after the initialization code... also don't cast the return value of malloc in C).

At the top, you declare

node *rootNode = NULL; 

If you don't run insertNode (successfully - See Matt's answer), the node will still be NULL when trying to print it and that's why you're getting the segfault.

The reason why the code segfaults when you uncomment the printf statement is because rootNode is a NULL pointer. Dereferencing this NULL pointer in the function call causes the segfault.

The reason that rootNode is a NULL pointer is that it is never changed by the code. Calling insertNode() results in the local variable n being set to the value that is stored in rootNode (in this case NULL). The changes to n in the insertNode() function do not change rootNode .

To fix the code you could change the insertNode and deleteNode functions to accept a pointer to the root node pointer. For example the insertCode() function would become:

void insertNode(int i, node **n) {
    if(*n == NULL) {
        (*n) = (node*)malloc(sizeof(node));
        (*n)->leftChildNode = NULL;
        (*n)->rightChildNode = NULL;
        (*n)->data = i;
    }
    else
    {
        if((*n)->data == i)
        {
            printf("\nThis value already exists in the tree!");
        }
        else
        {
            if(i > (*n)->data)
                insertNode(i, &(*n)->rightChildNode);
            else
                insertNode(i, &(*n)->leftChildNode);
        }
    }
}

You would also have to change the code to call insertNode() with a reference to rootNode insertNode(num, &rootNode);

I also recommend that you check the return values of the various scanf calls. If scanf("%d",x) returns 0 then the value not be converted to an int and the contents of x are undefined. Ideally the code would handle this case gracefully.

I think the probblem is with the signature for Insert function Try the below code and It will work

void insertNode(int i, node **n) {
    if(*n == NULL) {
        *n = (node*)malloc(sizeof(node));
        (*n)->leftChildNode = NULL;
        (*n)->rightChildNode = NULL;
        (*n)->data = i;
    }
    else 
    if((*n)->data == i)
        printf("\nThis value already exists in the tree!");
    else
    if(i > (*n)->data)
        insertNode(i, &((*n)->rightChildNode));
    else
        insertNode(i, &((*n)->leftChildNode));
    }

And use Insert Function as

insertNode(num, &rootNode);

Earlier the changes remain in the function Insert only. Use double pointer inside.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM