Thread: Deleting Binary Tree Node

  1. #1
    Registered User
    Join Date
    Jan 2014
    Location
    Hawaii
    Posts
    6

    Post Deleting Binary Tree Node

    Hello Everyone,
    I am having trouble with my deleteNode function, using recursion I am trying to delete a node from a binary tree. My tree is displayed as the following...
    Tree: (node)->[left child, right child]
    (k)->[g,p]
    (g)->[c,h]
    (c)->[ ,e]
    (e)->[ , ]
    (h)->[ , ]
    (p)->[m,t]
    (m)->[ , ]
    (t)->[s, ]
    (s)->[ , ]

    My code implementation to delete a node from the tree is..
    Code:
    /* 
     * Deallocate a node's space 
     */
    void destroyNode(Node * nodeptr)
    {
        free(nodeptr);
    }
    /* 
     * The deleteNode is incomplete.  It only deletes nodes
     * that are leaves.  Otherwise, it doesn't change the tree.
     */
    void deleteNode(Node ** ptr2link) 
    {
        Node ** nodeptrptr;
        Node * nodeptr;
    
    
        char c;
    
    
        /* Get the alphabet to delete */
        while(1) 
        {
               printf("Enter alphabet ('a' - 'z'): ");
               c = getchar();
               while(getchar() != '\n'); /* get rid of extra characters from stdin */
               if (c < 'a' || c > 'z') printf("\n Try again \n");
               else break;
        }
    
    
        /* Search for the node */
        nodeptrptr = searchNode(c, ptr2link);
        if (nodeptrptr == NULL)
        {
         printf("Could not find it\n");
         return; /* Couldn't find it */
        }
        
        /* Delete the node */
        /*if the node we found is empty: no subbranches delete it */
        nodeptr = *nodeptrptr;
        if (nodeptr->left == NULL && nodeptr->right == NULL) 
        {     /* A leaf */
               *nodeptrptr = NULL; 
    /* Delete the node from the tree  by NULLing the link from the parent node */
               destroyNode(nodeptr); /* Deallocate space back to memory */
            printf("DEBUG: DELETED NODE CHECK\n");
        }/*else if the node we want haves subbranches we need to cut off subbranches */
         else 
         {    /* if the node we are deleting have two childs */
            if( nodeptr->left != NULL && nodeptr->right != NULL)
            {
                deleteNode(&(nodeptr)->left);
                deleteNode(&(nodeptr)->right);
                /*then free or destroy node */
                destroyNode(nodeptr);
                printf("OK so you destroy the subbranch and node\n");
            }/*else if the node has a right child */
            else if(nodeptr->left == NULL && nodeptr->right != NULL)
            {
                deleteNode(&(nodeptr)->right);
                /*then free or destroy node */
                destroyNode(nodeptr);
                printf("OK so you destroy the right subbranch and node\n");
            }
            else if (nodeptr->left != NULL && nodeptr->right == NULL)
            {
                deleteNode(&(nodeptr)->left);
                /*then free or destroy node */
                destroyNode(nodeptr);
                printf("OK so you destroy the left subbranch and node\n");
            }
         }
        
    }
    when I execute my program and run delete command I got prompted twice display in the following....
    Code:
    Commands 
         (q) Quit
         (e) Insert an alphabet 
         (d) Delete an alphabet 
         (t) Display tree 
         (i) List the nodes in in-order
         (p) List the nodes in post-order
    Enter command: d
    Enter alphabet ('a' - 'z'): t
    Enter alphabet ('a' - 'z'): t
    Could not find it
    OK so you destroy the left subbranch and node

    And after displaying the tree I got this as my tree
    Tree: (node)->[left child, right child]
    (k)->[g,p]
    (g)->[c,h]
    (c)->[ ,e]
    (e)->[ , ]
    (h)->[ , ]
    (p)->[m,]
    (m)->[ , ]
    ()->[s, ]
    (s)->[ , ]


    The result did show that it is erased but when I try to add the erase node "t" back into the tree it still exist. I am stumped on what to do when using recursion way of deleting node. Did i used my pointers wrong or wrong recursion ?

    Thank you for your time to help and I apologize if I broke any rule here

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Having the rest of your code, so we could compile and run it ourselves, would be very helpful. You also didn't say whether this was a binary search tree (BST), or some other type of binary tree. I will assume BST. Usually when you delete a node, you don't delete the sub-tree. You delete just the node, and you move one of it's children up to replace it. See the Wikipedia section on deleting from BSTs for more info.

    If you are trying to do some other type of delete, or have some other type of tree, you need to give us more information so we can better help you.

  3. #3
    Registered User
    Join Date
    Jan 2014
    Location
    Hawaii
    Posts
    6
    I apologize for giving little info. I thought it might be asking you guys to do the whole hw for me, but nonetheless here is the source code of my binary search tree, and thank you for your time to help.

    To answer your question yes it is a binary search tree. My professor's code gave us originaly does not change any part of the tree when deleting a node with subbranches and the goal of this hw is to implement deleteNode to delete a node that haves subbranches. After reviewing how my professor implements other function with recursion like addNode, I thought I could do the same with deleteNode that got me to this problem.

    Code:
     
    /*
    * This program maintains a binary search tree.  It's to help you
     * understand pointers in C.
     *
     * The program first initializes a binary search tree. The
     * data in the node in the tree is a single text character
     * that ranges from 'a' to 'z'.  But initially, the tree is
     * empty.
     *
     * Then it gets comands from the user:
     *
     *   - (q) Quit
     *   - (e) Insert an alphabet
     *   - (d) Delete an alphabet
     *   - (t) List the nodes in the tree and their children
     *   - (i) List the nodes in in-order
     *   - (p) List the nodes in post-order
     *
     * The "(d) Delete" operation is not working.  If the node to delete is
     * a leaf then should delete.  Otherwise, it should not delete.
     * Also, "(p) List the nodes" in post-order is not working.
     * Your task is to make these work.
     *  
     *  You can compile by "gcc tree.c"
     */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    
    
    typedef struct nodeType {
      char data;
      struct nodeType * left;
      struct nodeType * right;
    } Node;
    
    
    /* 
     * The following creates and destroys nodes using dynamic
     * memory allocation system calls 
     */
    Node * createNode();  
    void destroyNode(Node * nodeptr);
    
    
    /* 
     * insertNode and deleteNode will insert and delete nodes.
     * addNode is called by insertNode, and searchNode is called
     * by deleteNode.
     * The deleteNode function is incomplete.  It only deletes
     * leaf nodes. One of your tasks is to have it be able to delete any
     * node in the tree. 
     */
    void insertNode(Node ** ptr2link);
    void addNode(Node * nodeptr, Node ** ptr2link);
    void deleteNode(Node ** ptr2link);
    Node ** searchNode(char c, Node ** ptr2link);
    
    
    /*
     * listInOrder and listPostOrder will list the nodes in-order
     * and post-order.  One of your tasks is to implement
     * listPostOrder.  This is pretty easy, kind of a warm up
     * exercise.
     */
    void listInOrder(Node * nodeptr);
    void listPostOrder(Node * nodeptr);
    
    
    /* 
     * displayTree will display the nodes of the tree and
     * their children.  This is useful to check if your
     * program is working and updating the tree properly.
     * It's also useful to identify nodes in the tree for
     * deleting.  For example, the current deleteNode function
     * only deletes leaves.  displayTree can be used
     * to determine which nodes are leaves.
     * displayTreeNodes is called by displayTree.
     */
    void displayTree(Node * nodeptr);
    void displayTreeNodes(Node * nodeptr);
    
    
    main()
    {
    
    
    char cmd;   /* Command from user */
    char c;
    Node * head;  /* Head of the binary search tree */
    
    
    head = NULL;  /* Initialize the binary search tree to be empty */
    
    
    printf("Welcome to the binary search tree!\n\n");
    
    
    while(1) {
       printf("Commands \n");
       printf("     (q) Quit\n");
       printf("     (e) Insert an alphabet \n");
       printf("     (d) Delete an alphabet \n");
       printf("     (t) Display tree \n");
       printf("     (i) List the nodes in in-order\n");
       printf("     (p) List the nodes in post-order\n");
    
    
       printf("Enter command: ");
       cmd = getchar();
       while(getchar() != '\n'); /* get rid of extra characters from stdin */
    
    
       if (cmd == 'q') return; /* Quit */
       else if (cmd == 'e') insertNode(&head);
       else if (cmd == 'd') deleteNode(&head); /* This is incomplete */
       else if (cmd == 't') displayTree(head);
       else if (cmd == 'i') { /* Display nodes in-order */
          printf("\n");
          printf("In-order list:");
          listInOrder(head);
          printf("\n\n");
       }
       else if (cmd == 'p') {
          printf("\n");
          printf("Post-order list:");
          listPostOrder(head);
           /*You must implement display nodes post-order */
          /*printf(" post-order list not implemented");  delete this line after implementing */
          printf("\n\n");
       }
       else {
          printf("Invalid command, try again\n");
       }
     }
    }
    
    
    
    
    /* 
     * Create a node and return pointer to the node 
     */
    Node * createNode()
    {
        Node * nodeptr;
        nodeptr = (Node *) malloc(sizeof(Node));
        nodeptr->left = NULL;
        nodeptr->right = NULL;
    
    
        return nodeptr;
    }
    
    
    /* 
     * Deallocate a node's space 
     */
    void destroyNode(Node * nodeptr)
    {
        free(nodeptr);
    }
    
    
    /* 
     * The deleteNode is incomplete.  It only deletes nodes
     * that are leaves.  Otherwise, it doesn't change the tree.
     */
    void deleteNode(Node ** ptr2link) 
    {
        Node ** nodeptrptr;
        Node * nodeptr;
    
    
        char c;
    
    
        /* Get the alphabet to delete */
        while(1) 
        {
               printf("Enter alphabet ('a' - 'z'): ");
               c = getchar();
               while(getchar() != '\n'); /* get rid of extra characters from stdin */
               if (c < 'a' || c > 'z') printf("\n Try again \n");
               else break;
        }
    
    
        /* Search for the node */
        nodeptrptr = searchNode(c, ptr2link);
        if (nodeptrptr == NULL)
        {
         printf("Could not find it\n");
         return; /* Couldn't find it */
        }
        
        /* Delete the node */
        /*if the node we found is empty: no subbranches delete it */
        nodeptr = *nodeptrptr;
        if (nodeptr->left == NULL && nodeptr->right == NULL) 
        {     /* A leaf */
               *nodeptrptr = NULL; 
    /* Delete the node from the tree  by NULLing the link from the parent node */
               destroyNode(nodeptr); /* Deallocate space back to memory */
            printf("DEBUG: DELETED NODE CHECK\n");
        }/*else if the node we want haves subbranches we need to cut off subbranches */
         else 
         {    /* if the node we are deleting have two childs */
            if( nodeptr->left != NULL && nodeptr->right != NULL)
            {
                deleteNode(&(nodeptr)->left);
                deleteNode(&(nodeptr)->right);
                /*then free or destroy node */
                destroyNode(nodeptr);
                printf("OK so you destroy the subbranch and node\n");
            }/*else if the node has a right child */
            else if(nodeptr->left == NULL && nodeptr->right != NULL)
            {
                deleteNode(&(nodeptr)->right);
                /*then free or destroy node */
                destroyNode(nodeptr);
                printf("OK so you destroy the right subbranch and node\n");
            }
            else if (nodeptr->left != NULL && nodeptr->right == NULL)
            {
                deleteNode(&(nodeptr)->left);
                /*then free or destroy node */
                destroyNode(nodeptr);
                printf("OK so you destroy the left subbranch and node\n");
            }
         }
        
    }
    
    
    /* 
     * Searches for a node in the tree with data = c
     * Input:  data c
     *         Initially, ptr2link points to the head that points to first 
     *             node in the tree.  After that it points to the link
     *             that points to the node.  It's the same as nodeptrptr in
     *             the lecture notes.
     * Output: ptr to the link, that points to the node
     *         A return value of NULL indicates the node wasn't found
     */ 
    Node ** searchNode(char c, Node ** ptr2link)
    {
    
    
        Node * nodeptr;
    
    
        if (*ptr2link == NULL) return NULL;
        else 
        {
               nodeptr = *ptr2link; /* nodeptr points to the node */
               if (nodeptr->data == c) /* This is the node */
                      return(ptr2link);
               else if (nodeptr->data > c) /* Search to the left */
                      return searchNode(c, &(nodeptr->left));
               else /* Search to the right */
                  return searchNode(c, &(nodeptr->right));
        }
    }
    
    
    
    
    /* 
     * This listing is basically an in-order tree traversal 
     */
    void listInOrder(Node * nodeptr)
    {
        if (nodeptr == NULL)  return; /* Nothing left to print */
    
    
        listInOrder(nodeptr->left);
        printf(" %c ",nodeptr->data);
        listInOrder(nodeptr->right);
    }
    
    
    
    
    /* 
     * This needs to be implemented 
     */
    void listPostOrder(Node * nodeptr)
    {
        if (nodeptr == NULL) return; /*Nothing left to print */
        /*Post order print is the leaves displat than the branch thus */
        listPostOrder(nodeptr->left);
        listPostOrder(nodeptr->right);
        printf("%c", nodeptr->data);
        
        
    }
    
    
    
    
    /* 
     * Input:  newnodeptr points to the new node to insert
     *         Initially, ptr2link points to the head that points to first 
     *             node in the tree.  After that it points to the link
     *             that points to the node.  It's the same as nodeptrptr in
     *             the lecture notes.
     * Post Condition:  node is inserted into the binary search tree
     */ 
    void addNode(Node * newnodeptr, Node ** ptr2link)
    {
        Node * nodeptr;
    
    
        if (ptr2link == NULL) 
        {
               printf("Something went wrong in addNode\n");
               return; 
        }
        else 
        {
           nodeptr = *ptr2link; /* nodeptr points to a node in the tree */
               if (nodeptr == NULL) { /* insert new node */
                  *ptr2link = newnodeptr;  /* This will change the value of a link in the tree */
                   return;
               } 
               else if (nodeptr->data == newnodeptr->data) 
               {/* Node is already in tree */
                      printf("NODE ALREADY EXIST\n");
                      return;
               }
               else if (nodeptr->data > newnodeptr->data) /* Search to the left */
                  addNode(newnodeptr, &(nodeptr->left));
               else /* Search to the right */
                  addNode(newnodeptr, &(nodeptr->right));
        }
    }
    
    
    
    
    void insertNode(Node ** ptr2link)
    {
        char c;
        Node * nodeptr;
    
    
        while(1) 
        {
               printf("Enter alphabet ('a' - 'z'): ");
               c = getchar();
               while(getchar() != '\n'); /* get rid of extra characters from stdin */
               if (c < 'a' || c > 'z') printf("\n Try again \n");
               else break;
        }
    
    
        /* Create a node */
        nodeptr = createNode();
        nodeptr->data = c;
    
    
        /* Add the node to the binary search tree */
        addNode(nodeptr, ptr2link);
    }
    
    
    
    
    void displayTree(Node * nodeptr)
    {
        printf("\nTree: (node)->[left child, right child]\n");
        displayTreeNodes(nodeptr);
        printf("\n");
    }
    
    
    void displayTreeNodes(Node * nodeptr)
    {
        Node * leftptr; 
        Node * rightptr;
    
    
        if (nodeptr == NULL) return;
        else 
        {
               /* Print current node and its children */
               printf("(%c)->",nodeptr->data);
               leftptr = nodeptr->left;
               if (leftptr==NULL) printf("[ ,");
               else printf("[%c,",leftptr->data);
               rightptr = nodeptr->right;
               if (rightptr==NULL) printf(" ]");
               else printf("%c]",rightptr->data);
               printf("\n");
    
    
               /* Continue printing descendent nodes */
               displayTreeNodes(leftptr);
               displayTreeNodes(rightptr);
        }
    }
    Last edited by mgy; 02-18-2014 at 11:35 AM.

  4. #4
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    First, compile at maximum warning level:
    Code:
    $ make foo
    gcc -Wall -ggdb3 -pedantic -std=gnu99 -O0 -o foo foo.c -lm -lpthread -lrt
    foo.c:85:1: warning: return type defaults to ‘int’ [enabled by default]
    foo.c: In function ‘main’:
    foo.c:115:25: warning: ‘return’ with no value, in function returning non-void [enabled by default]
    foo.c:90:10: warning: unused variable ‘c’ [-Wunused-variable]
    Declare main to explicitly return an int (line 85): int main(). When you return from main (line 115), always return an int: return 0; works here. Read this and this. The problems listed in the second link are the same problems you get from a return with no value, in function returning int.

    As for the problems you mentioned:

    The result you see doesn't really show a deleted node/sub-tree. It is showing you that it thinks the nodes are still in the tree, but the data in the nodes is somewhat broken. That is because after you delete a node, you need to set the parent's pointer to the child you deleted, to NULL so the tree knows there is nothing below that point.

    It asks you twice for the node to delete because you recursively call deleteNode, and that function always asks for the node to delete (lines 180-187), so you ask the user each time you go one layer down in the tree. This maybe should be split up into multiple functions. When building the tree, you have insert (which gets input and calls add), add which does the recursive adding of a node, and create, which handles memory allocation. Mirror that in your delete. Have one function to get the node to delete (maybe called removeNode) which calls the recursive function, another to do the recursive delete (maybe called deleteNode), and one to handle freeing the memory. deleteNode should (the recursive function) should be the one to set the child pointers to NULL after you free the child elements.

  5. #5
    Registered User
    Join Date
    Jan 2014
    Location
    Hawaii
    Posts
    6
    Thank you for the input and other links to help me understand this more. I will reply back with your suggestion later on today.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Code for deleting a tree node not working
    By Mini in forum C Programming
    Replies: 2
    Last Post: 10-09-2010, 05:16 AM
  2. Getting the parent of a node in a binary tree
    By budala in forum C Programming
    Replies: 4
    Last Post: 09-18-2009, 12:36 PM
  3. Delete a node in a binary tree
    By alice in forum C Programming
    Replies: 2
    Last Post: 07-05-2004, 05:01 AM
  4. delete node for a binary tree
    By AmazingRando in forum C Programming
    Replies: 4
    Last Post: 10-27-2003, 10:45 PM
  5. binary tree node structure
    By Kirsten in forum C Programming
    Replies: 2
    Last Post: 04-26-2002, 08:02 PM