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;
}
`
Related
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();
}
}
So I have code for a Binary Search Tree in C that works fine for me. However when I add code for a BST deletion, my program will crash during that deletion.
It gives me an error saying Access violation reading location 0x00000000.
I think this is something to do with passing NULL pointers, or something. Maybe I read that somewhere, or maybe that's completely wrong and I'm silly.
Anyway, here is my code for my AVL deletion. If you could help me in getting my program working and help me understand what I did wrong, I'd be very grateful. I'll also include my function for finding the minimum node, because I feel as if it may be the culprit.
AVL min_node(AVL self)
{
/* A AVL node to keep track of the current node. */
AVL current = self;
/* This loop finds the minimum node, by traversing the tree until the leftmost node is discovered. */
while (!empty_tree(current))
{
current = current->left;
}
/* Returns the tree. */
return current;
}
AVL delete(AVL self, long id)
{
if (self != NULL)
{
if (id == self->student_id)
{
if (self->left != NULL)
{
AVL successor = min_node(self->right);
self->student_id = successor->student_id;
self->right = delete(self->right, self->student_id);
}
else
{
AVL to_free = self;
if (self->left)
{
self = self->left;
}
else
{
self = self->right;
}
free(to_free);
}
}
else if (id < self->student_id)
{
self->left = delete(self->left, id);
}
else
{
self->right = delete(self->right, id);
}
}
/*NEW SHIT*/
int balance = getBalance(self);
//Left Left Case
if (balance > 1 && getBalance(self->left) >= 0)
{
return rotateRight(self);
}
//Left Right Case
if (balance > 1 && getBalance(self->left) < 0)
{
self->left = leftRotate(self->left);
return rotateRight(self);
}
//Right Right Case
if (balance < -1 && getBalance(self->right) <= 0)
{
return leftRotate(self);
}
//Right Left Case
if (balance < -1 && getBalance(self->right) > 0)
{
self->right = rotateRight(self->right);
return leftRotate(self);
}
return self;
}
UPDATE: So it seems to be crashing on one of two lines in delete function:
self->student_id = successor->student_id;
OR
AVL successor = min_node(self->right);
EDIT 2: Upon request, I've included my entire avl.c file.
#include <stdlib.h>
#include <stdbool.h>
#include "avl.h"
bool names_match(char* name_one, char* name_two)
{
if (strcmp(name_one, name_two) == 0)
{
return true;
}
else
{
return false;
}
}
bool empty_tree(AVL self)
{
if (self == NULL)
{
return true;
}
else
{
return false;
}
}
AVL leftRotate(AVL self)
{
AVL y = self->right;
AVL T2 = y->left;
y->left = self;
self->right = T2;
return y;
}
AVL rotateRight(AVL self)
{
AVL x = self->left;
AVL T2 = x->right;
x->right = self;
self->left = T2;
return x;
}
int getBalance(AVL node)
{
if (node == NULL)
{
return 0;
}
return height(node->left) - height(node->right);
}
AVL insert(AVL self, long id)
{
if (self == NULL)
{
self = (AVL)malloc(sizeof(struct avlNode));
self->student_id = id;
self->left = self->right = NULL;
}
else if (id < self->student_id)
{
self->left = insert(self->left, id);
}
else if (id > self->student_id)
{
self->right = insert(self->right, id);
}
/*NEW SHIT*/
int balance = getBalance(self);
//Left Left Case
if (balance > 1 && id < self->left->student_id)
{
return rotateRight(self);
}
//Right Right Case
if (balance < -1 && id > self->right->student_id)
{
return leftRotate(self);
}
//Left Right Case
if (balance > 1 && id > self->left->student_id)
{
self->left = leftRotate(self->left);
return rotateRight(self);
}
//Right Left Case
if (balance < -1 && id < self->right->student_id)
{
self->right = rotateRight(self->right);
return leftRotate(self);
}
//Return unchanged pointer (i dunno why. could probably be void)
return self;
}
/* === AVL MINIMUM NODE ===
Finds the minimum node in a AVL.
*/
AVL min_node(AVL self)
{
/* A AVL node to keep track of the current node. */
AVL current = self;
/* This loop finds the minimum node, by traversing the tree until the leftmost node is discovered. */
while (!empty_tree(current->left))
{
current = current->left;
}
/* Returns the tree. */
return current;
}
AVL delete(AVL self, long id)
{
if (self != NULL)
{
if (id == self->student_id)
{
if (self->left != NULL)
{
AVL successor = min_node(self->right);
self->student_id = successor->student_id;
self->right = delete(self->right, self->student_id);
}
else
{
AVL to_free = self;
if (self->left)
{
self = self->left;
}
else
{
self = self->right;
}
free(to_free);
}
}
else if (id < self->student_id)
{
self->left = delete(self->left, id);
}
else
{
self->right = delete(self->right, id);
}
}
/*NEW SHIT*/
if (self == NULL)
{
return self; //ADDED TODAY
}
int balance = getBalance(self);
//Left Left Case
if (balance > 1 && getBalance(self->left) >= 0)
{
return rotateRight(self);
}
//Left Right Case
if (balance > 1 && getBalance(self->left) < 0)
{
self->left = leftRotate(self->left);
return rotateRight(self);
}
//Right Right Case
if (balance < -1 && getBalance(self->right) <= 0)
{
return leftRotate(self);
}
//Right Left Case
if (balance < -1 && getBalance(self->right) > 0)
{
self->right = rotateRight(self->right);
return leftRotate(self);
}
return self;
}
/* === AVL NODE COUNT ===
Counts the number of nodes in the AVL.
*/
int number_of_nodes(AVL self)
{
/* If the tree is empty, return a count of 0 nodes. */
if (empty_tree(self))
{
return(0);
}
/* If the tree is not empty, but its left and right nodes are, return a count of 1 node. */
else if (empty_tree(self->left) && empty_tree(self->right))
{
return(1);
}
/* If the tree is not empty, and its left and right nodes are also not empty, run this function recursively in the left and right nodes. */
else
{
return(1 + (number_of_nodes(self->left) + number_of_nodes(self->right)));
}
}
/* === AVL HEIGHT ===
Returns the total height of a AVL.
*/
int height(AVL self)
{
/* If the tree is empty, return a count of 0 nodes. */
if (empty_tree(self))
{
return 0;
}
/* If the tree is not empty, run this fucntion recursively on the left and right branches, returning the max of the two. */
else
{
return 1 + max(height(self->left), height(self->right));
}
}
/* === PRINT AVL ===
Prints a AVL in pre-order.
*/
void print_pre_order(AVL self)
{
/* If the tree isn't empty, print the node's ID and then run this function recursively on the left and then the right nodes,
to print pre order. */
if (!empty_tree(self))
{
printf("%d", self->student_id);
printf("\n");
print_pre_order(self->left);
print_pre_order(self->right);
}
}
/* === SEARCH AVL ===
Searches a AVL for a particular node.
*/
bool searchTree(AVL self, long id)
{
if (!empty_tree(self))
{
/* If the node's ID matches the input ID, return true. */
if (self->student_id == id)
{
return true;
}
/* If the node's ID doesn't match the input ID, run this function recurseively on the appropriate node. */
else
{
if (self->student_id > id)
{
return searchTree(self->left, id);
}
else if (self->student_id < id)
{
return searchTree(self->right, id);
}
}
}
return false;
}
void destroy_tree(AVL self)
{
/* If the tree is not empty, free each node in the tree by running this function recursively on the left and right branches. */
if (!empty_tree(self))
{
destroy_tree(self->left);
destroy_tree(self->right);
free(self);
}
}
EDIT 3: Interesting development. The AVL tree being used are actually in a linked list, with each node containing an AVL tree. Now I've come to realise (through lots of testing) that a node on the AVL tree can be deleted, IF its the first one that's been built. Very interesting, and even more annoying.
I think the problem is with the 'self->right' which you are passing to the function. If 'self' is a pointer which I am assuming it is then in my opinion you should pass the 'address' of the 'self' like so '&(self->right)' and the current should be assigned the value of the '&self' like so 'current = *self'. Then I think it could work.
I think I can correct with what I am saying if am I provided with the entire code but I think you get the gist
I'm attempting to remove a given value from a binary search tree. The function returns 1 if the given value was present, and 0 if it wasn't. I don't think I'm returning values properly. The proper values seem to be removed, but I'm printing a removal message when I shouldn't be, indicating that the function is returning 0 when it shouldn't be. Can anybody help me spot my error? Thanks.
/*Remove data from BST pointed to by rootRef, changing root if necessary.
* For simplicity's sake, always choose node's in-order
* successor in the two-child case.
* Memory for removed node should be freed.
* Return 1 if data was present, 0 if not found. */
int removeBST(struct TreeNode** rootRef, int data)
{
struct TreeNode* heir;
struct TreeNode* prev;
if(*rootRef == NULL)
{
return 0;
}
if(data < (*rootRef)->data)
{
removeBST(&(*rootRef)->left, data);
}
else if(data > (*rootRef)->data)
{
removeBST(&(*rootRef)->right, data);
}
else
{
struct TreeNode* temp;
if((*rootRef)->right == NULL)
{
temp = *rootRef;
*rootRef = (*rootRef)->left;
free(temp);
}
else if((*rootRef)->left == NULL)
{
temp = *rootRef;
*rootRef = (*rootRef)->right;
free(temp);
}
else
{
heir = (*rootRef)->left;
prev = *rootRef;
while(heir->right != NULL)
{
prev = heir;
heir = heir->right;
}
(*rootRef)->data = heir->data;
if(prev != *rootRef)
{
prev->right = heir->left;
}
else
{
prev->left = heir->left;
}
free(heir);
}
return 1;
}
return 0;
}
When it calls itself recursively, it needs to return the value from the recursive call. So change:
removeBST(&(*rootRef)->left, data);
to:
return removeBST(&(*rootRef)->left, data);
and similarly for the right-hand case. Without this, it is just falling through and returning 0 for these cases.
Replace
if(data < (*rootRef)->data)
{
removeBST(&(*rootRef)->left, data);
}
else if(data > (*rootRef)->data)
{
removeBST(&(*rootRef)->right, data);
}
with
if(data < (*rootRef)->data)
{
return removeBST(&(*rootRef)->left, data);
}
else if(data > (*rootRef)->data)
{
return removeBST(&(*rootRef)->right, data);
}
When you call the function, you did not use the return value.
In this video (a section/recitation for an online course called CS50), around 1h00m00s, the student instructor goes into pointers-to-pointers and why it is more efficient useful to implement insert on the binary tree this way. At least, that is what I'm getting from the argument.
I did a recursive implementation both ways. I don't see why Option A is better than Option B in the below...perhaps you could help me reason this out or point me in the right direction if I'm misunderstood?
Option A (with pointers-to-pointers)
bool insert(int value, node* tree)
{
node** tmptree = &tree;
// make sure the tree itself isn't null
if(*tmptree != NULL)
{
if(value == (*tmptree)->value)
{
return false;
}
else if(value < (*tmptree)->value)
{
tmptree = &(*tmptree)->left;
// we must be at a null leaf!
if(*tmptree == NULL)
{
// make sure we built a leaf
*tmptree = build_node(value);
if(*tmptree == NULL)
{
return false;
}
return true;
}
else
{
return insert(value, *tmptree);
}
}
else
{
tmptree = &(*tmptree)->right;
if(*tmptree == NULL)
{
*tmptree = build_node(value);
if(*tmptree == NULL)
{
return false;
}
return true;
}
else
{
return insert(value, *tmptree);
}
}
}
return false; // if the tree is null
}
Option B (regular ptrs)
bool insert(int value, node* tree)
{
if(tree != NULL)
{
if(value == tree->value)
{
return false;
}
else if(value < tree->value)
{
if(tree->left == NULL)
{
node* tmp = build_node(value);
if(tmp != NULL)
{
tree->left = tmp;
return true;
}
return false;
}
else
{
return insert(value, tree->left);
}
}
else
{
if(tree->right == NULL)
{
node* tmp = build_node(value);
if(tmp != NULL)
{
tree->right = tmp;
return true;
}
return false;
}
else
{
return insert(value, tree->right);
}
}
}
return false; // if the tree is null
}
The build_node function:
node* build_node(int value)
{
node* node = malloc(sizeof( node ));
if(node == NULL)
return NULL;
node->value = value;
node->left = NULL;
node->right = NULL;
return node;
}
I believe you have misunderstood why there is a pointer-to-pointer in the original code. The "Option a" doesn't make any sense, there is no advantage of using pointer-to-pointer just for the sake of it.
The only reason you would use pointer-to-pointer is because you want to change the pointed-to address and return it to the caller.
For example
void func (int** ptr)
{
*ptr = something;
}
func(&my_ptr);
// is the very thing same as
int* func (int* ptr)
{
return something;
}
my_ptr = func(my_ptr);
You can't use the second version and type ptr = something inside the function, because ptr is a local variable and will cease to exist once you leave the function. Assigning something to it won't affect the original pointer at the caller's side.
The only advantage of the pointer-to-pointer version is that the returned type can be used for something else, like for example returning an error code.
And that seems to be exactly why the guy in that video used it. His function looks like
bool insert (int value, node** tree);
where the *tree is assigned to point at another address from inside the function and the bool is used as a status code, when he reaches the end of a tree branch.
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;
}
}
}