modified depth first traversal of tree - c

I got this question in an interview with amazon.
I was asked to perform a depth first traversal of a tree, without using recursion or stack. I could use a parent pointer for each node, as a part of the structure, but nothing else other than that.(for ex, a "visited" variable" or anything).
Please suggest me an algorithm.

The parent pointer is actually all you need. The trick is to consume the tree as you traverse it.
Ugly pseudocode:
cur = treeroot;
while (1) { // Get to bottom of tree
if (cur.hasLeft) {
cur = left;
} else if (cur.hasRight) {
cur = right;
} else {
break;
}
// cur is now the bottom node
while (1) {
doStuff(cur); // output cur, perform op on it, whatever
if (!cur.hasParent) { // Done with traversal
break;
}
prev = cur; // So we can tell which way we came up to the parent.
cur = cur.parent;
if (cur.hasLeft && cur.left == prev) { // Delete left child; it's done
cur.hasLeft = false;
} else if (cur.hasRight && cur.right == prev) { // Delete right child; it's done
// Note: "else" not desirable if a node should not be able to have the same child in two spots
cur.hasRight = false;
}
if (cur.hasLeft) { // Go all the way to the bottom of the left child
cur = cur.left;
while (1) {
if (cur.hasLeft) {
cur = cur.left;
} else if (cur.hasRight) {
cur = cur.right;
} else {
break;
}
}
} else if (cur.hasRight) { // Go all the way to the bottom of the right child
cur = cur.right;
while (1) {
if (cur.hasLeft) {
cur = cur.left;
} else if (cur.hasRight) {
cur = cur.right;
} else {
break;
}
}
}
}

For a 'hacky' solution you can use the fact that pointers are usually 4 byte aligned (i.e, last two bits are 0) and use those two bits as your visited flag.

Here is my proposition for a binary tree. The language is C#. It's a private method of a binarTree class that holds ints
private Node DFS(int value)
{
Node current = this.root;
if(current.data == value) return current;
while(true)
{
//go down-left as far as possible
while(current.leftChild != null)
{
current = current.leftChild;
if(current.data == value) return current;
}
//leftChild is null, but maybe I can go right from here
while(current.leftChild == null && current.rightChild != null)
{
current = current.rightChild;
if(current.data == value) return current;
}
if(current.leftChild == null && current.rightChild == null)
{
// Ok, I got to a leaf. Now I have to get back to the last "crossroads"
// I went down-left from, but there was also down-right option
while(current.parent != null &&
(current == current.parent.rightChild ||
current.parent.rightChild == null))
{
current = current.parent;
}
if(current.parent == null) return null;
// Ok If I'm here, that means I found the crossroads mentioned before
// I'll go down-right once and then I should try down-left again
current = current.parent.rightChild;
if(current.data == value) return current;
}
}
}
If it's not a binary tree, then things get more complicated of course, but the logic is similar. Go down to the leaf taking the first possible child at each level. Once you reach a leaf you go up. Every time you look up at a parent you check if the child you are supposed to come from was the last in parent's list. If not, you take next child and go down again. If yes, you go up and check the following parent. If you get back to the root you searched the whole tree.
EDIT
Ok search and traversals are distinct things, my bad. Here is some modified code for traversals
preorder:
public void preorderTraversal()
{
Node current = this.root;
Console.WriteLine(" item: {0} ", current.data);
while(true)
{
while(current.leftChild != null)
{
current = current.leftChild;
Console.WriteLine(" item: {0} ", current.data);
}
while(current.leftChild == null && current.rightChild != null)
{
current = current.rightChild;
Console.WriteLine(" item: {0} ", current.data);
}
if(current.leftChild == null && current.rightChild == null)
{
while(current.parent != null &&
(current == current.parent.rightChild ||
current.parent.rightChild == null))
{
current = current.parent;
}
if(current.parent == null)
{
return;
}
else
{
current = current.parent.rightChild;
Console.WriteLine(" item: {0} ", current.data);
}
}
}
}
inorder:
public void inorderTraversal()
{
Node current = this.root;
while(true)
{
while(current.leftChild != null)
{
current = current.leftChild;
}
Console.WriteLine(" item: {0} ", current.data);
while(current.leftChild == null && current.rightChild != null)
{
current = current.rightChild;
Console.WriteLine(" item: {0} ", current.data);
}
if(current.leftChild == null && current.rightChild == null)
{
while(current.parent != null &&
(current == current.parent.rightChild ||
current.parent.rightChild == null))
{
current = current.parent;
if(current.rightChild == null)
{
Console.WriteLine(" item: {0} ", current.data);
}
}
if(current.parent == null)
{
return;
}
else
{
Console.WriteLine(" item: {0} ", current.parent.data);
current = current.parent.rightChild;
}
}
}
}
postorder:
public void postorderTraversal()
{
Node current = this.root;
while(true)
{
while(true)
{
if(current.leftChild != null)
{
current = current.leftChild;
}
else if(current.rightChild != null)
{
current = current.rightChild;
}
else
{
break;
}
}
while(current.parent != null &&
(current == current.parent.rightChild ||
current.parent.rightChild == null))
{
Console.WriteLine(" item: {0} ", current.data);
current = current.parent;
}
Console.WriteLine(" item: {0} ", current.data);
if(current.parent == null)
{
return;
}
else
{
current = current.parent.rightChild;
}
}
}

If you have a parent pointer, then you can unwind up the tree without a stack. The only other problem during unwind is "do I need to visit the other child(ren)?" This can be answered simply by comparing pointer values to work out if you've just returned from the left child or the right child (or generalise to N children).
EDIT
Pseudocode (untested):
p_last = NULL;
p = p_head;
descend = true;
while (NULL != p)
{
p_tmp = p;
if (descend)
{
// ... Node processing here...
if (0 == p->num_children)
{
// No children, so unwind
p = p_parent;
descend = false;
}
else
{
// Visit first child
p = p->child[0];
}
}
else
{
// Find the child we just visited
for (i = 0; i < p->num_children; i++)
{
if (p_last == p->child[i])
{
break;
}
}
if (i == num_children-1)
{
// Processed last child, so unwind
p = p_parent;
}
else
{
// Visit next child
p = p->p_child[i+1];
descend = true;
}
}
p_last = p_tmp;
}

This shows how I'd do it in C. It demonstrates both pre-order and post-order traversal, and is generalised for 0..N children of each node.
struct node {
struct node *parent;
struct node *child[NCHILD];
};
void dfs(struct node *head, void (*visit_preorder)(struct node *n), void (*visit_postorder)(struct node *n))
{
struct node *current = head;
struct node *prev = head;
while (current)
{
int i;
/* preorder traversal */
if (prev == current->parent)
visit_preorder(current);
/* Find first child to visit */
for (i = NCHILD; i > 0; i--)
{
if (prev == current->child[i - 1])
break;
}
while (i < NCHILD && current->child[i] == NULL)
i++;
prev = current;
if (i < NCHILD)
{
/* Descend to current->child[i] */
current = current->child[i];
}
else
{
/* Postorder traversal */
visit_postorder(current);
/* Ascend back to parent */
current = current->parent;
}
}
}

Related

C Order Statistic Tree: Recursive Deletion Node Counting

I am trying to make an order statistic tree of some sort where I have to keep track of the size (nodeCount variable on each node) recursively. It orders a tree of objects by comparing the memory locations. I just need help on the delete recursive method, which I have figured out besides how to count the nodes for deletion. I will include my fully working insert method as an example. Any help would be appreciated, thank you :)
DELETE RECURSIVE (NEED HELP)
`
bool deleteR(TreeKey k, TreeNode** tptr) {
TreeNode* curr = *tptr;
// base case: root contains null
if (curr == NULL) {
// node not there: return false
return false;
}
else if(less(k, getKey(curr->value))) {
// our data is less, so go left
return deleteR(k, &curr->left);
}
else if(less(getKey(curr->value), k)) {
// our data is greater, so go right
return deleteR(k, &curr->right);
}
// at this point, we've found our node
// if either of the current node's subtrees is null:
// - replace the current node in the tree with the "other" subtree
// - free the current node
// - return true
if (curr->left == NULL) {
*tptr = curr->right;
free(curr);
return true;
}
else if (curr->right == NULL) {
*tptr = curr->left;
free(curr);
return true;
}
// call helper-function
inorderSuccessorReplace(curr, &curr->right);
return true;
}
static void inorderSuccessorReplace(TreeNode* target, TreeNode** spot) {
TreeNode* curr = *spot;
if (curr->left == NULL) {
// found our spot
target->value = curr->value;
*spot = curr->right;
free(curr);
}
else {
inorderSuccessorReplace(target, &curr->left);
}
}
`
INSERT RECURSIVE METHOD
`
bool insertR(TreeData d, TreeNode **tptr) {
TreeKey key = getKey(d);
if(*tptr == NULL) {
*tptr = newTreeNode(d);
(*tptr)->nodeCount = size(*tptr); // updates nodeCount
return true;
}
else if(less(key, getKey((*tptr)->value))) {
(*tptr)->nodeCount = size(*tptr) + 1; // updates nodeCount
// item is less: recursively insert to the left
return insertR(d, &(*tptr)->left);
}
else if(less(getKey((*tptr)->value), key)) {
(*tptr)->nodeCount = size(*tptr) + 1; // updates nodeCount
// item is greater: recursively insert to the right
return insertR(d, &(*tptr)->right);
}
else {
// item already in the tree: return false
return false;
}
}
int size(TreeNode* t) {
if (t == NULL) {
return 0;
}
return t->nodeCount;
}
`

NULL assignment to a structure pointer is not working through function. What to do?

I am trying to implement BST deletion. According to algorithm, we can delete a leaf directly. Now I'm assigning NULL to leaf directly and still this node remains as it is.
In the test case I gave tried to delete leaf and it is not working.
Please help!
struct node * delet(long data, struct node* root)
{
int i=1;
struct node *temp = root,*t;
while(temp != 0)
{
if(data < temp->data)
{
i=2*i;
temp = temp->l;
}
else if(data > temp->data)
{
i = (2*i)+1;
temp = temp->r ;
}
else
{
printf("%d\n",i);
break;
}
}
if(temp->l == 0 && temp->r == 0)
{
temp = 0;
return root;
}
else if(temp->l == 0)
{
temp->data = temp->l->data;
temp->l = 0;
}
else if(temp->r == 0)
{
temp->data = temp->r->data;
temp->r = 0;
}
else
{
t = temp;
t = t->r;
while(t->l != 0)
{
t = t->l;
}
temp->data = t->data;
if(t->r != 0)
{
t->data = t->r->data;
t->r = 0;
return root;
}
else
{
t = 0;
return root;
}
}
}
temp = 0; doesn't delete the leaf from the tree, just nulls a local variable.
You want to null some node's l or r in order to remove a node from the tree.
Try keeping the parent as well and once temp points to the leaf, nullify temp's parent r or l.
Same goes for t = 0; later on.
Note David's comment about first releasing this memory..
For example (assuming not deleting the root):
...
if(data < temp->data)
{
i=2*i;
parent = temp;
temp = temp->l;
}
else if(data > temp->data)
{
i = (2*i)+1;
parent = temp;
temp = temp->r ;
}
else
{
printf("%d\n",i);
break;
}
...
if(temp->l == 0 && temp->r == 0)
{
if (parent->l == temp)
parent->l = 0;
else
parent->r = 0;
// Free temp if needed
return root;
}
...
Also note that you have:
else if(temp->l == 0)
{
temp->data = temp->l->data;
Which is a dereference of a null pointer (temp->l is NULL), and the same thing for temp->r == 0 case.
Then you have
temp->l = 0;
but you're already in a temp->l == 0 case, so I don't think this is what you meant.

Deleting a node from a binary search tree without recursion

I have a binary search tree. I want to delete a node from it:
void deleteANode(struct node *head, int value) {
//let us find the node
struct node *temp = head;
struct node *parent = NULL;
//let us find the node
while (temp != NULL) {
if (value > temp->data) {
parent = temp;
temp = temp->right;
} else
if (value < temp->data) {
parent = temp;
temp = temp->left;
} else {
//let us check for child nodes
//
if (temp->left == NULL && temp->right == NULL) {
printf("Deleting a leaf.\n");
temp = NULL;
printf("Set temp null.\n");
free(temp);
break;
} else
if (temp->left == NULL || temp->right == NULL) {
printf("Deleting a one child.\n");
//one of the child is null
if (temp->left != NULL) {
parent->left = temp->left;
} else {
parent->right = temp->right;
}
free(temp);
} else {
printf("Deleting two child parent.\n");
//both of them are not NULL
//need to find the pre-order successor
struct node *temp2 = temp->right;
while (temp2->left != NULL) {
temp2 = temp2->left;
}
//found the successor.
temp->data = temp2->data;
free(temp);
}
break;
}
}
}
I am trying to delete a leaf node in this block:
if (temp->left == NULL && temp->right == NULL) {
printf("Deleting a leaf.\n");
temp->data = NULL;
printf("Set temp null.\n");
free(temp);
break;
}
But the above code doesn't work.
I am calling the above method:
deleteANode(head, 3);
The preorder traversal is remains same before and after:
5 4 3 10 7 20 Deleting a leaf. Set temp null.
=============== 5 4 3 10 7 20
What am I doing wrong.
Updated as per #pstrjds comments:
if (temp->left == NULL && temp->right == NULL ) {
printf("Deleting a leaf.\n");
parent->left = NULL;
parent->right = NULL;
free(temp);
temp = NULL;
printf("Set temp null.\n");
break;
}
It's working fine for leaf node. Need to work for node with two children.
In the block of code which is deleting a leaf you are not actually freeing the node nor are you updating the parent node to no longer point to it.
if ( temp -> left == NULL && temp -> right == NULL )
{
printf("Deleting a leaf.\n");
if (parent->left == temp)
{
parent->left = NULL;
}
else
{
parent->right = NULL;
}
free(temp);
temp = NULL;
printf("Set temp null.\n");
break;
}
You could actually remove the line temp = NULL and change the break; to a return statement.
Does your code really work?
It should be like this:
printf("Deleting two child parent.\n");
Node* temp2 = temp->right;
while(temp2->left != NULL)
{
parent = temp2;
temp2 = temp2->left;
}
temp->data = temp2->data;
parent->left = NULL;
delete temp2;
return;
Java Solution
// Java program to demonstrate delete operation in binary search tree
class BinarySearchTree
{
/* Class containing left and right child of current node and key value*/
class Node
{
int key;
Node left, right;
public Node(int item)
{
key = item;
left = right = null;
}
}
// Root of BST
Node root;
// Constructor
BinarySearchTree()
{
root = null;
}
// This method mainly calls deleteRec()
void deleteKey(int key)
{
root = deleteRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node deleteRec(Node root, int key)
{ Node x=root;
Node parent =null;
/* Base Case: If the tree is empty */
while(x!=null)
{
if(x.key>key)
{ parent=x;
x=x.left;
}
else if(x.key<key)
{parent=x;
x=x.right;
}
else
{
if(x.left==null&&x.right==null)
{
System.out.println(x.key+"y1");
if(parent.left==x)
parent.left=null;
else if(parent.right==x)
parent.right=null;
x=null;
break;
}
else
{
System.out.println(x.key+"y2");
if(x.left==null)
{
if(parent.right==x)
parent.right=x.right;
else if(parent.left==x)
parent.left=x.right;
System.out.println(x.key+"yes");
x=null;
break;
}
else if(x.right==null)
{
if(parent.left==x)
parent.left=x.left;
else if(parent.right==x)
parent.right=x.left;
x=null;
break;
}
else
{
Node temp=x;
Node px=null;
temp=temp.right;
while(temp.left!=null)
{ px=temp;
temp=temp.left;
}
x.key=temp.key;
if(px.left==temp)
px.left=null;
else if(px.left==temp)
px.right=null;
temp=null;
break;
}
}
}
}
return root;
}
int minValue(Node root)
{
int minv = root.key;
while (root.left != null)
{
minv = root.left.key;
root = root.left;
}
return minv;
}
// This method mainly calls insertRec()
void insert(int key)
{
root = insertRec(root, key);
}
/* A recursive function to insert a new key in BST */
Node insertRec(Node root, int key)
{
/* If the tree is empty, return a new node */
if (root == null)
{
root = new Node(key);
return root;
}
/* Otherwise, recur down the tree */
if (key < root.key)
root.left = insertRec(root.left, key);
else if (key > root.key)
root.right = insertRec(root.right, key);
/* return the (unchanged) node pointer */
return root;
}
// This method mainly calls InorderRec()
void inorder()
{
inorderRec(root);
}
// A utility function to do inorder traversal of BST
void inorderRec(Node root)
{
if (root != null)
{
inorderRec(root.left);
System.out.print(root.key + " ");
inorderRec(root.right);
}
}
// Driver Program to test above functions
public static void main(String[] args)
{
BinarySearchTree tree = new BinarySearchTree();
/* Let us create following BST
50
/ \
30 70
/ \ / \
20 40 60 80 */
tree.insert(50);
tree.insert(30);
tree.insert(20);
tree.insert(40);
tree.insert(70);
tree.insert(60);
tree.insert(80);
System.out.println("Inorder traversal of the given tree");
tree.inorder();
System.out.println("\nDelete 20");
tree.deleteKey(20);
System.out.println("Inorder traversal of the modified tree");
tree.inorder();
System.out.println("\nDelete 30");
tree.deleteKey(30);
System.out.println("Inorder traversal of the modified tree");
tree.inorder();
System.out.println("\nDelete 50");
tree.deleteKey(50);
System.out.println("Inorder traversal of the modified tree");
tree.inorder();
}
}

Implementing doubly linked list in C(deleteing a node at any position)

I have this function that deletes a node at any position of the doubly linked list. It is working fine if you have only one node. I tried to insert 3 nodes, then delete the last one, it just freezes.
Here are the functions I used:
int getpos(char ln[20])
{
int pos=1;
temp3=h;
if(temp3 == NULL)
{
printf("List empty");
return;
}
while(temp3->next!=NULL)
{
if(strcmp(temp3->lname,ln)==0)
{
break;
}
else
{
pos++;
}
}
return pos;
}
The function to get the position of the node to be deleted.
void del()
{
int i = 1, pos=0;
char ln[20];
temp2 = h;
printf("enter lname: ");
gets(ln);
pos=getpos(ln);
if ((pos < 1) || (pos >= count + 1))
{
printf("\n Error : Position out of range to delete");
return;
}
if (h == NULL)
{
printf("\n Error : Empty list no elements to delete");
return;
}
else
{
while (i < pos)
{
temp2 = temp2->next;
i++;
}
if (i == 1)
{
if (temp2->next == NULL)
{
printf("Node deleted from list");
free(temp2);
temp2 = h = NULL;
return;
}
}
if (temp2->next == NULL)
{
temp2->prev->next = NULL;
free(temp2);
printf("Node deleted from list");
return;
}
temp2->next->prev = temp2->prev;
if (i != 1)
temp2->prev->next = temp2->next; /* Might not need this statement if i == 1 check */
if (i == 1)
h = temp2->next;
printf("\n Node deleted");
free(temp2);
}
count--;
}
The function to delete the node.
In function getpos, you are not incrementing temp3->next, so the while loop is running forever.
By the way, a simple debugging attempt would have saved you the hassle of asking this question.
you can write somthing like this:
void delete_node(Node* pNode)
{
pNode->Data = pNode->Next->Data;
pNode->Next->Next->Previous = pNode;
Node* pTemp = pNode->Next;
delete(pNode->Next);
pNode->Next = pTemp;
}
This func. treats only nodes in the middle,
so just make sure to add edge cases - if the Node is first or last.

deleting an element in AVL trees in C

struct node *delete(struct node *root, int key)
{
struct node *remove_node;
if (root == NULL){
return root;
}
if ( key < root->key) {
root->left = delete(root->left, key);
} else if ( key > root->key) {
root->right = delete(root->right,key);
} else {
if ((root->left == NULL) && (root->right != NULL)){
remove_node = root->right;
*root = *remove_node;
deletetree(remove_node); // this is for free-ing the memory
} else if ((root->right == NULL) && (root->left != NULL)){
remove_node = root->left;
*root = *remove_node;
deletetree(remove_node);
} else if ((root->right == NULL) && (root->left == NULL)){
remove_node = root;
root = NULL;
} else {
remove_node = successor(root);
root->key = remove_node->key;
root->right = delete(root->right, remove_node->key);
}
}
if (root == NULL) {
return root;
if (balance_factor(root) == 2){
if (balance_factor(root->left) == -1) {
return single_right_rotation(root);
} else if (balance_factor(root->left) == 1) {
return double_left_rotation(root);
}
}
if (balance_factor(root) == -2) {
if (balance_factor(root->right) == -1) {
return single_left_rotation(root);
}
else if (balance_factor(root->right) == 1) {
return double_right_rotation(root);
}
}
}
return root;
}
Here's my code for deleting an element in an AVL tree. Everything seems to work fine, it handles all the case when node n has no children, one children and two children. But for some odd reason it does not balance the tree nor does it reaches that block of code.
Hopefully someone can help me debug the code cause I cannot find where "exactly" the error is coming from.
Thanks in Advance
PS: the successor function just returns the minimum element on the right tree of the node to be deleted and the deletetree deals with free-ing memory allocation stuffs.
Also i am 100% that my rotations work because it worked perfectly in my insert function.
You can use temp root, as reference and you can change like this:
struct node *localRoot = root;
And you change roots to localRoot, probably the problem is solved.
I hope it is helpfull.

Categories

Resources