How to properly insert/delete in a binary search tree in C? - c

I kinda have to put my previous C questions on hold cause this one is more important now...
I have already coded the insert and delete functions on my binary search tree but the delete function is incomplete. There's a couple of things I need help in...
1) Is my insert function good or can it be improved somehow?
2) My delete function lacks the deletion of a node with both the left and right childs. I've searched a lot in the past few hours but couldn't find a proper way to do it.
2.a) How should I delete a node with 2 child nodes?
2.b) As in the first question, is the delete function good or can it be improved? This one I know it can because I'm repeating lots of code in those ifs but I don't see how can I improve it, I need help on that too.
typedef struct sClientProfile *ClientProfile;
typedef struct sClientTree *ClientTree;
typedef struct sClientProfile {
char *clientName;
int clientAge;
int clientNIF;
} nClientProfile;
typedef struct sClientTree {
ClientProfile clientProfile;
char *clientName;
ClientTree leftTree;
ClientTree rightTree;
} nClientTree;
void addClientToTree(ClientTree *cTree, ClientProfile cProfile) {
if(!*cTree) {
ClientTree new = (ClientTree)malloc(sizeof(nClientTree));
if(!new) {
perror("malloc");
}
new->clientName = strdup(cProfile->clientName);
new->clientProfile = cProfile;
new->leftTree = NULL;
new->rightTree = NULL;
*cTree = new;
} else {
if(strcmp((*cTree)->clientName, cProfile->clientName) > 0) {
addClientToTree(&(*cTree)->leftTree, cProfile);
} else {
addClientToTree(&(*cTree)->rightTree, cProfile);
}
}
}
void deleteClientFromTree(ClientTree *cTree, char *cName) {
if(!cTree) return;
int nCompare = strcmp((*cTree)->clientName, cName);
if(nCompare > 0) {
deleteClientFromTree(&(*cTree)->leftTree, cName);
} else if(nCompare < 0) {
deleteClientFromTree(&(*cTree)->rightTree, cName);
} else {
if(!(*cTree)->leftTree && !(*cTree)->rightTree) {
ClientTree cliPtr = *cTree;
free(cliPtr->clientProfile);
free(cliPtr);
cliPtr->clientProfile = NULL;
cliPtr = NULL;
*cTree = NULL;
} else if(!(*cTree)->leftTree) {
ClientTree cliPtr = *cTree;
free(cliPtr->clientProfile);
free(cliPtr);
cliPtr->clientProfile = NULL;
*cTree = (*cTree)->rightTree;
} else if(!(*cTree)->rightTree) {
ClientTree cliPtr = *cTree;
free(cliPtr->clientProfile);
free(cliPtr);
cliPtr->clientProfile = NULL;
*cTree = (*cTree)->leftTree;
} else {
// MISSING DELETE CASE
}
}
}
You'll probably notice but let me just make 2 remarks:
This tree uses strings instead of the normal int representation. That's why I use strcmp() all the way, I think I'm using it right.
I'm not using recursion, I rather pass the pointer (of a structure pointer in this case) and work with that. It looks more clean somehow and in the future I want to return a success value if a node was deleted.
UPDATE BELOW:
I've already did my iterative version of the delete function but I don't like some things about it, maybe they can be improved (or not) but I can't see how. I've also tried to code the case it was missing, deleting a node with 2 childs, but it's not working as it should...
I've commented the whole code where I think the code can be improved and where's the problem. I've also named those problems as A, B (there's no B anymore), C and D so we can reference to them easily.
bool deleteClientFromTree(ClientTree *cTree, char *cName) {
if(!cTree) return FALSE;
ClientTree currPtr = *cTree;
ClientTree prevPtr = NULL;
int nCompare;
while(currPtr) {
nCompare = strcmp(currPtr->clientName, cName);
if(nCompare > 0) {
prevPtr = currPtr;
currPtr = currPtr->leftTree;
} else if(nCompare < 0) {
prevPtr = currPtr;
currPtr = currPtr->rightTree;
} else {
/*
* A)
*
* The following cases have 3 lines in common, the free()
* calls and return statement. Is there anyway to improve
* this code and make it more compact?
*
* Of course, the printf's are to be removed...
*/
if(!prevPtr && !currPtr->leftTree && !currPtr->rightTree) {
printf("CASE #1\n");
*cTree = NULL;
free(currPtr->clientProfile);
free(currPtr);
return TRUE;
} else if(!currPtr->leftTree || !currPtr->rightTree) {
printf("CASE #2\n");
if(prevPtr->leftTree == currPtr) {
prevPtr->leftTree = currPtr->rightTree;
} else {
prevPtr->rightTree = currPtr->leftTree;
}
free(currPtr->clientProfile);
free(currPtr);
return TRUE;
} else {
printf("CASE #3\n");
ClientTree tempPtr = currPtr->rightTree;
while(tempPtr->leftTree) {
tempPtr = tempPtr->leftTree;
}
/*
* C)
*
* This has a big problem...
*
* If you take a look at the ClientProfile structure,
* in the first post, you'll see two ints
* (clientNIF/clientAge) and one char* (clientName).
*
* The problem is that the following code line is only
* copying the integer data, not the string. For some
* reason, the string remains the old one.
*
* I tried to use strdup() directly on clientName like:
* currPtr->clientProfile->clientName = strdup(tempPtr->clientProfile->clientName);
* but it still doesn't work.
*
* Why everything is being copied but the strings?
*/
currPtr->clientProfile = tempPtr->clientProfile;
/*
* D)
*
* Is there anyway to not call the function itself
* and make the while loop once again and delete the
* corresponding leaf?
*/
return deleteClientFromTree(&currPtr->rightTree, tempPtr->clientProfile->clientName);
}
}
}
return FALSE;
}

When you delete a node, you have to do something about its children.
If there are no children - no problem. You just remove the node.
If there a left child, also no problem; you remove the node and move its left child into its place.
Same for the right child; just move the child into the place of the deleted node.
The problem comes when you want to delete a node which has both left and right children. You could move the left or the right child into the place of the deleted node, but what do you then do about the other child and its subtree?
Solution is this; you locate the logical successor to the node being deleted. By logical successor, I mean this; say you have a tree made of integers and you delete node with value 35, the logical successor is the next largest number. Ya? if you were doing an in-order walk, it would be the element you come to after the element you're deleting.
Now, there's a simple rule to find the logical successor; you go right one (you always have a right, because this is the case where you have two children) and then you go as far left as you can.
That element you end up at is the logical successor. It's larger than the deleted element (you went right at the start, remember?) but it's the smallest next largest element.
Now, that element ALWAYS has only one or no children - because you went left as far as you can, remember? so you can't go left any more - because there is no left - so that element has no children or just a right child and that means it falls into one of the easy-to-unlink catagories (no children or just one child). So unlinking this element is easy.
Now comes the cool bit - consider this; if that next largest element were in the same place in the tree as the element you want to delete, the tree would still be valid and correct - because everything to the left of each element is smaller, everything to the right is larger.
So what you do is this; you copy the user data in the next largest node into the node being deleted and you delete that next largest node (it has no children or just a right child, so it's easy to unlink and delete).
And that's it!
So, basically - find your logical successor, unlink him from the tree and put his user data into the element you're actually originally deleting (which you don't then delete, of course, because it's still physically part of the tree).

First off, you mentioned you aren't using recursion but each function has a logical path that calls itself.
On to the questions:
1)
Remove the recursion. This can get you in a lot of trouble if your tree is large enough to blow your stack. Gcc has limited support for tail recursion, but I wouldn't count on it.
2)
Typically, when you delete a child with two nodes, you promote the left or right node to the position the deleted node was in. (This is a highly simplistic case, I'm assuming your tree isn't balanced)
2.b)
Your delete code has some problems. I'd recommend walking through it with a few hypothetical situations. Immediately obvious to me was free'ing a pointer and then deferencing it:
free(cliPtr);
cliPtr->clientProfile = NULL;
Of course, you can always worry about style once you get the correctness thing squared away.

Ideally there are three cases for deletion of a node in BST:
Case 1:
X has no children: remove X
Case 2:
X has one children : Splice out X
Case 3:
X has two children : swap X with its successor and follow case #1 or #2
So for the missing delete case:
When X (node to delete) has two children, replace X with the successor of X and follow case #1 or case #2. You can also replace with its predecessor, might be a good alternative.
if ( X->left && X->right)
{
NODE *Successor = FindSuccessor(X);
X->data = Successor->data;
free(Successor);
}

this binary codes are insert, delete,search, and quit.
Examples:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Binary Tree {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
LinkedList ll = new LinkedList();
ll.add("\n"+"mai 0020");
ll.add("\n"+"king 0019");
ll.add("\n"+"maan 0002");
ll.add("\n"+"dimple 0024");
ll.add("\n"+"eman 0004");
ll.add("\n"+"lara 0005");
ll.add("\n"+"cute 0008");
ll.add("\n"+"irene 0011");
ll.add("\n"+"sheena 0030");
ll.add("\n"+"aisy 0003");
System.out.println("display: " + ll);
System.out.println("\n\n");
for(int c=0; c<=10; c++) {
System.out.println("select from: 1-insert, 2-delete," +
" 3-display, 4-search, 5-quit");
String x = br.readLine();
int y = Integer.parseInt(x);
switch (y) {
case 1: //inserting
System.out.println("input name");
String n= br.readLine();
System.out.println("input a list number");
String o = br.readLine();
int z = Integer.parseInt(o);
ll.add("\n"+n+" "+z);
break;
case 2: // delete
ll.removeFirst();
break;
case 3: //Display
System.out.println("\n\n"+"List of employee: " + ll);
System.out.println("\n\n");
break;
case 4: //search
System.out.println("\n");
System.out.println("Search");
System.out.println("first element of the Linkedlist is: "
+ ll.getFirst());
System.out.println("\n\n");
System.out.println("last element of linkedlist:"
+ ll.getLast());
break;
case 5: //quit
System.out.println("\n\n\n\n\n"
+ " Thank You Very Much!!!!!!!\n\n\n");
System.exit(0);
break;
}
}
}
}

int delete_value(Tree*&root,Tree*&find,Tree*&ptr,int numb){
if(find->value==number){
//the number exist in the root,so we should find the highest value inside the right brache and replace it with the root.
Tree*ptr2=NULL;
Tree*ptr3=NULL;//pointer pointing to the parent of the last element of ptr2.
ptr2=root->right;
while(ptr2!=NULL){
ptr3=ptr2;
ptr2=ptr2->left;
}
if(ptr2->right!=NULL){
ptr3->left=ptr2->right;
}
swap(ptr2->value,root->value);
delete ptr2;
ptr2=ptr3=NULL;
}
else{
while(find->value!=numb){
if(find->value!=numb){
ptr=find;
}
if(find->value < numb){
find=find->right;
return delete_value(root,find,ptr,numb);
}
else{
find=find->left;
return delete_value(root,find,ptr,numb);
}
}//end of while
}//end of else
//the pointer find is pointing at the element we want to delete.
//the pointer ptr is pointing at the element before the one's we want to delete.
//case 1:the element to delete don't have any children
if(find->right==NULL && find->left==NULL){
if(ptr->left=find){
ptr->left=NULl;
delete find;
}
else{
ptr->right=NULL;
delete find;
}
}//end of the first case.
//case 2:the element has one child it could be to the left or to the right.
//a-child to the right.
if( find->right!=NULL && find->left==NULL ){
Tree*ptr2=find->right;
while(ptr2!=NULL){
ptr2=ptr2->left;//find the highest value in the right branche and replace it with the delete element
}
swap(find->value,ptr2->value);
delete ptr2;
ptr2=NULL;
}
//b-child to the left.
if(find->right==NULL && find->left!=NULL){
Tree*ptr2=find->left;
//check wether the find element is to the right or to the left of ptr.
if(ptr->left==find){
ptr->left=ptr2;
delete find;
}
else{
ptr->right=ptr2;
delete find;
}
}//end of the second case.
//case3: the element has to children.
if(find->right!=NULL&&find->left!=NULL){
Tree*ptr2=find->left;
while(ptr2->right!=NULL){
ptr2=ptr2->right;
}
swap(ptr2->value,find->value);
delete ptr2;
ptr2=NULL;
}//end of case 3.
}//end of the function.

Related

Search and Inserting in a binary tree recursively

first of all happy new year. I was trying to fix a piece of code I've been stumped on for hours. (Note: I am not a solid coder.)
What I am trying to do is to write a function "searchInsert", which will take in a binary tree and some integer i. It will then try to find the integer i in the tree. If it's not there it is inserted into the tree.
Other information: If we do in fact find the integer in the tree, return a pointer pointing to the node of to it. If we do not find it as we said before, insert it in BUT return a pointer pointing to the root of the tree.
I also must do this recursively.
Now I have tested it using an arbitrary tree along with i = 98, as follows:
Before what it looks like.
4
/ \
2 6
/ \ / \
1 3 5 7
After, what it should look like:
4
/ \
2 6
/ \ / \
1 3 5 7
\
98
But my code doesn't seem to be working.
treelink searchInsert(treelink t, TreeItem i){
treelink keyNode = NULL;
if (t == NULL) {
t = insertTreeNode(t, i);
} else if(i < t->item){
keyNode = searchInsert(t->left,i);
} else if(i > t->item){
keyNode = searchInsert(t->right,i);
} else {
keyNode = t;
return keyNode;
}
return t;
}
Other important notes: treelink is a pointer to a binary tree. Assume insertTreeNode works as it was a function given to us.
Any help would be appreciated thanks.
Among other problems, you have lost all context when you realize that you have not found the item that you are looking for:
if ( t == NULL ) {
t = insertTreeNode(t, i) ;
}
So you are always calling insertTreeNode with NULL as the first argument.
While recursion is a great way to step through a tree, you might instead want to create a pointer and iterate through the tree, so that you have the original t around when you decide to call insert.
{
treelink ptr= t ;
while ( ptr )
{
if ( ptr-> item == i ) return ptr ;
ptr= ( ptr-> item > i ) ? ptr-> left : ptr-> right ;
}
return insertTreeNode( t, i ) ;
}
A new node is created, but it is not linked to the tree. You never change your left and right pointers.
what you need is to update the link after recursive call, e.g.:
else if (i < t->item) {
t->left = searchInsert(t->left, i);
} ...
But then of course you cannot simply return a pointer to a found item if it's found, otherwise it would break the tree. That's because the statement of your task is NOT recursive: you have to return either root or an existing (inner) node. So you might want to write a recursive function which e.g. always returns a pointer to the root, but also returns a pointer to a found item (through an additional treelink* argument).
Or maybe it would be simpler to split the function into two: search which returns a pointer to an existing node, and insert which returns a pointer to the root. Both of them would be recursive and quite simple.

Having trouble deleting elements in doubly linked list

I've been trying for about 5 hours to get this code to work properly, and the code is written based on hours of internet research.
I have modified it several times, all of which gave me segmentation faults, so this is the only version that runs.
What is happening, is that the code is cycling through, and deleting not only the element you want to get rid of, but all elements preceding it. So, if you want to delete the last element, everything in the list goes. Or, if you wanted to delete the second element, the first and second go, and so on.
It thinks that every name entered is the top name for some reason.
static void menu_delete_employee(void)
{
char deletename[MAX_NAME_LENGTH+1];
char namecheck[MAX_NAME_LENGTH+1];
int errorcheck = 0;
int foundit = 0;
fprintf(stderr, "Enter the name of the employee you wish to delete\n");
gets(deletename);
employee_list = top;
employee_list->name;
do
{
strcpy (namecheck, employee_list->name);
printf("namecheck = %s\n", namecheck);
errorcheck = (strcmp (namecheck, deletename));
printf("errorcheck = %i\n", errorcheck);
switch (errorcheck)
{
case 0:
{
printf("This is the right name\n");
foundit = 1;
if (employee_list->prev == NULL)
{
printf("top name\n");
top = employee_list->next;
}
else
{
if (employee_list->next == NULL)
{
printf("last one\n");
temp = employee_list->prev;
temp-> next = NULL;
free (employee_list);
}
else
{
printf("somewhere in the middle");
temp = employee_list->prev;
temp->next = employee_list->next;
employee_list->next->prev = temp;
free (employee_list);
}
}
printf("delete successful\n");
break;
}
default:
{
printf("not this one\n");
errorcheck = 0;
employee_list = employee_list->next;
break;
}
}
}
while (foundit == 0);
if (foundit == 0)
printf("Name not recognised\n.");
return;
}
Any help would be much appreciated.
Maybe the doubly-linked list is not built up the way you think it should. This has to be checked first.
Assuming the topology is correct, there are still a couple of issues with this code:
employee_list->name; (just above the do loop): what is this?
strcpy (namecheck, employee_list->name); : you do not need to copy, this is just a shorthand, so namecheck could be a (const) string pointer.
switch (errorcheck) : this has only 2 arms, why don't you use an if ?
if (employee_list->prev == NULL) ...: you just move the top pointer here but do not delete the top item, this will cause memory leaks. You also do not set the prev pointer of the next-to-top item to NULL.
In the "somewhere in the middle" part: you free employee_list which is the current position pointer. The next item to be processed should be temp->next, right? This is probably your problem because you do not take care of moving the current pointer along. Moreover, it is much better to set a pointer explicitly called tobedeleted to the item to be deleted, make sure the pointer used to iterate along the list (employee_list in your case) is moved appropriately, and when *tobedeleted is appropriately isolated out from the doubly linked list then issue the free(tobedeleted) command.
employee_list = employee_list->next; : you should check for employee_list turning into NULL at the last item, and exit the loop. Otherwise Bad Things will happen.
Final advice: you really need to consult a good C book... Kernighan and Ritchie
for instance. Way better than "Internet research".

Implementing a deletion function for a binary search tree in C

I've been trying to implement a function in C that deletes a node in a binary tree that should (theoretically) take care of three all cases, i.e.:
Node is a leaf
Node has one child
Node has two children
Is there a way to handle the whole deletion function without checking separately each case? As a commenter below noted I do check for a lot of cases and perhaps the whole problem can be addressed recursively by checking for one fundamental case.
I'm particularly interested in the case where I delete a node within the tree that has a parent and itself is a parent of two children nodes.
Both answers below have been useful but I don't think they address the problem in its entirety.
Here's what I have:
typedef struct Node
{
int key;
int data;
struct Node *left;
struct Node *right;
struct Node *parent;
} Node;
/* functions that take care of inserting and finding a node and also traversing and freeing the tree */
...
void delete(Node *root, int key)
{
Node *target = find(root, key); // find will return the node to be deleted
Node *parent = target->parent; // parent of node to be deleted
// no children
if (target->left == NULL && target->right == NULL)
{
// is it a right child
if (target->key > parent->key)
parent->right = NULL;
// must be a left child
else
parent->left = NULL;
free(target);
}
// one child
else if ((target->left == NULL && target->right != NULL) || (target->left != NULL && target->right == NULL))
{
// here we swap the target and the child of that target, then delete the target
Node *child = (target->left == NULL) ? target->right : target->left;
child->parent = parent;
if (parent->left == target) parent->left = child;
else if (parent->right == target) parent->right = child;
free(target);
}
// two children
else
{
// find the largest node in the left subtree, this will be the node
// that will take the place of the node to be deleted
Node *toBeRepl = max(target->left);
// assign the data of the second largest node
target->key = toBeRepl->key;
target->data = toBeRepl->data;
// if new node immediately to the left of target
if (toBeRepl == target->left)
{
target->left = toBeRepl->left;
Node *newLeft = target->left;
if (newLeft != NULL) newLeft->parent = target;
}
else
{
delete(target->left, toBeRepl->key);
// Node *replParent = toBeRepl->parent;
// replParent->right = NULL;
}
}
I would greatly appreciate your feedback.
edit: Just to clarify, I'm trying to delete a particular node without touching its subtrees (if there are any). They should remain intact (which I've handled by swapping the values of the node to be deleted and (depending on the case) one of the nodes of its substrees).
edit: I've used as a reference the following wikipedia article:
http://en.wikipedia.org/wiki/Binary_search_tree#Deletion
Which is where I got the idea for swapping the nodes values in case of two children, particularly the quote:
Call the node to be deleted N. Do not delete N. Instead, choose either
its in-order successor node or its in-order predecessor node, R.
Replace the value of N with the value of R, then delete R.
There is some interesting code in C++ there for the above case, however I'm not sure how exactly the swap happens:
else //2 children
{
temp = ptr->RightChild;
Node<T> *parent = nullptr;
while(temp->LeftChild!=nullptr)
{
parent = temp;
temp = temp->LeftChild;
}
ptr->data = temp->data;
if (parent!=nullptr)
Delete(temp,temp->data);
else
Delete(ptr->rightChild,ptr->RightChild->data);
}
Could somebody please explain what's going on in that section? I'm assuming that the recursion is of a similar approach as to the users comments' here.
I don't see any "inelegance" in the code, such formatting and commented code is hard to come by. But yes, you could reduce the if-else constructs in your delete function to just one case. If you look at the most abstract idea of what deletion is doing you'll notice all the cases basically boil down to just the last case (of deleting a node with two children).
You'll just have to add a few lines in it. Like after toBeRepl = max(left-sub-tree), check if it's NULL and if it is then toBeRepl = min(right-sub-tree).
So, Case 1 (No children): Assuming your max() method is correctly implemented, it'll return NULL as the rightmost element on the left sub-tree, so will min() on the right sub-tree. Replace your target with the toBeRepl, and you'll have deleted your node.
Case 2 (One child): If max() does return NULL, min() won't, or vice-versa. So you'll have a non-NULL toBeRepl. Again replace your target with this new toBeRepl, and you're done.
Case 3 (Two children): Same as Case 2, only you can be sure max() won't return NULL.
Therefore your entire delete() function would boil down to just the last else statement (with a few changes). Something on the lines of:
Node *toBeRepl = max(target->left);
if toBeRepl is NULL
{
toBeRepl = min(target->right);
}
if toBeRepl is not NULL
{
target->key = tobeRepl->key;
target->data = toBeRepl->data;
deallocate(toBeRepl); // deallocate would be a free(ptr) followed by setting ptr to NULL
}
else
{
deallocate(target);
}
I would do it using recursion, assuming that you have null at the end of your tree, finding null would be the 'go back' or return condition.
One possible algorithm would be:
Node* delete(Node *aNode){
if(aNode->right != NULL)
delete(aNode->right);
if(aNode->left != NULL)
delete(aNode->left);
//Here you're sure that the actual node is the last one
//So free it!
free(aNode);
//and, for the father to know that you're now empty, must return null
return NULL;
}
It has some bugs, for sure, but is the main idea.
This implementation is dfs like.
Hope this helps.
[EDIT] Node *aNode fixed. Forgot the star, my bad.
I finished this a long time ago and I thought it would be good to add a sample answer for people coming here with the same problem (considering the 400+ views this question has accumulated):
/* two children */
else
{
/* find the largest node in the left subtree (the source), this will be the node
* that will take the place of the node to be deleted */
Node* source = max(target->left);
/* assign the data of that node to the one we originally intended to delete */
target->key = source->key;
target->data = source->data;
/* delete the source */
delete(target->left, source->key);
}
Wikipedia has an excellent article that inspired this code.

handling the tail part of a non-tail recursive function when converting it to an iterative function

When converting a non-tail recursive function to an iterative function using your own made stack what is the general approach to take care of the part of the code that comes after the recursion call aka the tail?
The following function is supposed to explore all the possible paths in a maze, revisiting a previsited path in order to visit other paths in the stack:
struct node{
int id;
bool free;
int neighborNode[4];
int toProcess;
} nodeMap[100];
void findPath(int current){
visited[current] = true;
int i;
for (i=0; i < 4; i++){
if(nodeMap[nodeMap[current].neighborNode[i]].free == true && visited[nodeMap[current].neighborNode[i]] == false && nodeMap[current].neighborNode[i] != -1){
path[cc] = nodeMap[nodeMap[current].neighborNode[i]].id;
cc++;
findPath(nodeMap[current].neighborNode[i]);
path[cc] = nodeMap[current].id;
cc++;
}
}
}
The recursive part of the code is easily convertible to an iteration (I have used a field toProcess to imitate the index of the loop cause it is not saved in the stack and is needed for processing all the childs):
void findPath(){
if (isEmpty())
return;
else {
node temp = pop();
visited[temp.id] = true;
if (temp.toProcess < 3) {
temp.toProcess++;
push(temp);
temp.toProcess--;
}
if(nodeMap[temp.neighborNode[temp.toProcess]].free == true && visited[temp.neighborNode[temp.toProcess]] == false && temp.neighborNode[temp.toProcess] != -1){
path[cc] = nodeMap[temp.neighborNode[temp.toProcess]].id;
cc++;
push(nodeMap[temp.neighborNode[temp.toProcess]]);
}
}
}
But the part where the algorithm moves backwards to revisit previously seen nodes to explore other possible paths (the tail) i.e. path[cc] = nodeMap[current].id; & cc++; does not seem to fit in the iterative version of the method!
Is there a general approach to this? Or every case is different? In anyways, do you have any suggestion how to implement the tail part in this case?
The stack solution is nice and easy with tail-recursive functions, but as in your example, since you are doing something after the recursive call, you need to figure out a way to perform those operations after the call has ended.
The following is a possible solution:
struct stack_element
{
... your_stuff...
bool expanded;
};
In the code:
stack_element e;
... fill e
e.expanded = false;
push(e);
while (!empty())
{
e = pop();
if (e.expanded)
{
... do the stuff that was supposed to be done
... after e and all its children are processed
}
else
{
e.expanded = true;
push(e); // push e, so it would be visited again
// once all children are processed
for (every child of e)
if (they met the conditions)
{
... do the stuff before
stack_element child;
... fill child
child.expanded = false;
push(child);
}
}
}
What this basically does is, visits each node twice. Once when being expanded, at which point you execute the stuff before the recursive call, and another time once all its children have finished processing, at which point you execute the stuff after the recursive call.
Note that, you may need to save some states, such as maybe cc and current along with the node, so that you would be able to do the if (e.expanded) part correctly.
Side suggestion: Use a for loop as you have done in the recursive method, which is more clear than using toProcess.
In your case, that execution on one branch of children affects visiting or not visiting the others, you can follow the following approach:
Each time you get a node, check if it meets the necessary conditions. If it does, do the processing before the call of that node. Then like before, push it again so it will be visited again and the post-processing would be done. This way, every time you just push the children, and later decide if they are good or not:
struct stack_element
{
... your_stuff...
bool expanded;
... save also cc, current and i
};
stack_element e;
... fill e
e.expanded = false;
push(e);
while (!empty())
{
e = pop();
if (e.expanded)
{
... do the stuff that was supposed to be done
... when function called with e is returning and
... after the function returns to parent
}
else if (conditions for are met)
{
... do the stuff that was supposed to be done before
... e is recursively called and at the beginning of the
... function
e.expanded = true;
push(e); // push e, so it would be visited again
// once all children are processed
for (every child of e, in reverse order)
{
stack_element child;
... fill child
child.expanded = false;
push(child);
}
}
}
After looking at the exact code, here's the converted version:
struct stacknode{
int id;
int parent;
bool free;
bool expanded;
};
int cc = 0;
void findPath2(int current){
// special case for the first call:
visited[current] = true;
// expand the first node, because when the first node is popped,
// there was no "stuff before recursion" before it.
int i;
for (i=3; i >= 0; --i){
// Put the neighbors on the stack so they would be inspected:
stacknode child;
child.id = nodeMap[current].neighborNode[i];
child.parent = current;
child.free = nodeMap[child.id].free;
child.expanded = false;
push(child);
}
while (!isEmpty())
{
stacknode cur = pop();
if (cur.expanded == true)
{
// Now, it's like a return from a recursive function
// Note: cur.id will be nodeMap[current].neighborNode[i] because that was the value the function was called with
// Stuff at the end of the function:
path[0]=current; // Note: this is kind of absurd, it keeps getting overwritten!
// Stuff after recursion:
cc++; // note that path[0] is reserved for first node, so you should first increment cc, then set path[cc]
path[cc] = nodeMap[cur.parent].id; // nodeMap[current].id: current was the parent of
// nodeMap[current].neighborNode[i] for which the function was called
}
else
{
// Now, it's like when the recursive function is called (including stuff before recursion)
// Note: cur.id will be nodeMap[current].neighborNode[i] because that was the value the function was called with
// Check whether child was supposed to be added:
if(cur.id != -1 && nodeMap[cur.id].free == true && visited[cur.id] == false)
// Node: Put cur.id != -1 in the beginning. Otherwise, you would possibly check
// nodeMap[-1] and visited[-1] which is not nice
{
cur.expanded = true;
push(cur);
// Stuff before recursion:
cc++;
path[cc] = nodeMap[cur.id].id; // in cur.id, nodeMap[current].neighborNode[i] was stored
// Stuff at the beginning of function call:
visited[cur.id] = true;
// The body of the function:
for (i=3; i >= 0; --i){
// Put the neighbors on the stack so they would be inspected:
stacknode child;
child.id = nodeMap[cur.id].neighborNode[i];
child.parent = cur.id;
child.free = nodeMap[child.id].free;
child.expanded = false;
push(child);
}
}
}
}
// end of special case for first call:
path[0] = current;
}
Note that the reason it starts to get complicated is the existence of cc which is a global variable. If you had a recursive function that didn't use global variables, the conversion would have been simpler.
A general approach to convert recursion into iteration it to use a kind of event loop that repetedly pops events from a stack and executes their handlers. I'm going to first write some pseudocode which is similar to your recursive function, so it will be easier to understand the conversion:
recurse (node)
{
for (i = 0; i < 4; i++) {
if (condition(node, i)) {
recurse(next_node(node, i));
}
}
}
What we do now is split this recursive function into a sequence of operations - however, instead of writing it explicitly, we define each operation as an event and its corresponding event handler, and in case there is more work to be done after this operation, the handler will push this further work to the stack prior to performing its operation.
my_iterative_function ()
{
// build the event stack and push the initial event
EventStack stack;
stack.push(NewRecurseEvent(node = first_node));
// pop and execute events
while (!stack.isEmpty()) {
Event ev = stack.pop();
ev.executeHandler();
}
}
RecurseEventHandler (node)
{
// We are at the beginning of the "recurse" function.
// Push iteration 0 (we could optimize this and just do it here).
stack.push(NewIterationEvent(node = node, i = 0));
}
IterationEventHandler (node, i)
{
// Unless this is the last iteration, push the next iteration
// to be executed after this iteration is complete. It will work
// with the same node, but 'i' one greater.
if (i < 3) {
stack.push(NewIterationEvent(node = node, i = i + 1));
}
// do the work of this iteration
if (condition(node, i)) {
# Initiate the recursion by pushing.
# It is crutial to understand that the event loop will pop this event,
# and all events pushed by it, recursively, before
# popping the continuation event we pushed above.
# That is, it will behave just like the recursive variant.
stack.push(NewRecurseEvent(node = next_node(node, i)));
}
}
It depends on the language how to actually implement this pseudocode. In C, the event object can be a tagged union that holds arguments to various event handlers, and you can have the event loop just directly perform the event handler actions:
struct event {
int type; // RECURSE_EVENT or ITERATION_EVENT
union {
struct {
node node;
} recurse_event;
struct {
node node;
int i;
} iteration_event;
};
};
while (!stack.isEmpty()) {
struct event ev = stack.pop();
switch (ev.type) {
case RECURSE_EVENT: {
node n = ev.recurse_event.node;
...
} break;
case ITERATION_EVENT: {
node n = ev.iteration_event.node;
int i = ev.iteration_event.i;
...
} break;
}
}
Since your actual recursive function is more complex than my simple example because of the part that follows the recursive call, you will need more events to handle this. For example, you can add another kind of event to handle the post-recursion step:
IterationEventHandler (node, i)
{
if (i < 3) {
stack.push(NewIterationEvent(node = node, i = i + 1));
}
if (condition(node, i)) {
// This PostEvent will be executed after the recursive work,
// but before the next iteration pushed above.
stack.push(NewPostEvent(node = node, i = i));
stack.push(NewRecurseEvent(node = next_node(node, i)));
}
}
PostEventHandler (node, i)
{
// do your post-recursion work here
}
It is easy to understand this if you consider that, when looking at a single event handler, all work will be performed in the reverse order it was pushed. For example, at the IterationEventHandler above, first the recursion will be performed, then the post-recursion step, and finally the next iteration step will begin (if at all). In even simpler terms, each push can be understood as a possibly-recursive function call, except that these calls would execute from the bottom up.
Do note that this is a general approach. It is probably possible to build a compiler that converts any recursive function into such an event loop. Also, this approach is not only an elegant way to convert recursion into iteration; the "stack event loop" idea is very practical in design of event-driven software, particularly so if you also have the ability to dequeue events that have been pushed but not yet executed. I've explained this in my answer to this question.

Deleting nodes in BST using free(N)

I'm coding a binary search tree and I'm having a little trouble finding a way to delete node effectively.
I have this code :
struct node* deleteNode(int i, struct node *N)
{
if (N==NULL)
{
return NULL;
}
else if (i<N->value)
{
N->size--;
N->lChild=deleteNode(i,N->lChild);
}
else if (i>N->value)
{
N->size--;
N->rChild=deleteNode(i,N->rChild);
}
else if (N->lChild==NULL)
{
return N->rChild;
}
else if (N->rChild==NULL)
{
return N->lChild;
}
else
{
N->size--;
N->value=findMin(N->rChild);
N->rChild=deleteNode(N->value,N->rChild);
}
return N;
}
And N is a node structure which have 5 fields : value, lChild, rChild, size, height.
In fact what I'm doing here is to make the tree not to point toward the node that I want to delete but when I'm trying to put something like :
else if (N->rChild==NULL)
{
free(N);
N=NULL;
return N->lChild;
}
Or every similar looking code, it doesn't work. Can someone point me in the right direction please?
Thank you.
First of all you're saying N=NULL and then calling N->lchild N is null and pointing to nothing so how do you expect to get the lchild value?
Since this is homework I won't give a direct answer but hints.
To delete the node, check if it has children, if it doesnt free it and remove references to it such as the parents child ptr.
If it has 1 child swap the ptr that points to the node you want to delete with the child and free the node. The same applies if you also have 2 children.

Resources