I'm trying this question for sometime but couldn't figure out the algorithm. My preference is to do it iteratively. Till now, I've figure out something but not sure on some point.
Currently, My algorithm looks like:
First traverse the tree to find the node
While traversing the tree, keep track of the previous node.
if you find the node, check if left child is present then that is successor return.
if left child is not present then check if right child is present the that is successor and return.
if the node(is left to the parent) and don't have left or right child then we've saved the prev node earlier then either prev or prev's right child is the successor.
But what if the node we found is in the right to parent and don't have left or right child how to find successor of this node?
May be there are many flaws in this algorithm as still I've not understand all the cases properly. If anyone has any idea or algorithm please share.
Thanks in advance.
when you find a node in preorder, to find its successor is just travesing to its next node.
what I was thinking first is the relationship of a node and its successor's values in pre-oder, but I found that it seems not very clear like the relationship in in-order. I think there is only one step beteen a node and its successor(if exists) : just move on travesing. So I design this algorithm.
my algorithm below is based on preorder travesal, it can run on a binary tree,not only BST.
#define NOT_FOUND -1
#define NEXT 0
#define FOUND 1
struct node {
struct node *p;//parent,but useless here
struct node *l;//left child
struct node *r;//right child
int value;
};
int travese(struct node* bnode, int* flag,int value)
{
if(bnode == NULL)
return 0;
else
{
if(*flag == FOUND)
//when the successor is found,do pruning.
return 1;
else if(*flag == NEXT) {
printf("successor:%d\n",bnode->value);
*flag = FOUND;
return 1;
}
else if(*flag == NOT_FOUND && bnode->value == value)
*flag = NEXT;
travese(bnode->l,flag,value);
travese(bnode->r,flag,value);
}
return 0;
}
and use it by:
int flag = NOT_FOUND;
travese(root,&flag,value);
if(flag == NEXT || flag == NOT_FOUND)
printf("no successor.\n");
EDIT:
turning a recurrence algorithm to a iterative one is not difficult by using a stack like below:
int preorder_travese_with_stack(struct node* bnode, int* flag,int value)
{
if(bnode == NULL)
return 0;
struct stack s;//some kind of implement
push(s,bnode);
while(NotEmpty(s) && *flag) {
struct node *curNode = pop(s);
if(*flag == NEXT) {
printf("successor:%d\n",curNode->value);
*flag = FOUND;
return 1;
}
else if(*flag == NOT_FOUND && curNode->value == value)
*flag = NEXT;
push(s,curNode->r);
push(s,curNode->l);
}
return 0;
}
but according to your comment and original description, I think the one you want is iterative algorithm without a stack.here it is.
After thinking ,searching and trying, I wrote one. When travse the tree iteratively without stack , the parent of a node is not useless any more. In a path, some nodes is visited not only once, and you need to record its direction at that time.
int preorder_travese_without_stack(struct node *root,int value,int *flag)
{
int state=1;
//state: traveral direction on a node
//1 for going down
//2 for going up from its left chlid
//3 for going up from its right child
struct node *cur = root;
while(1) {
if(state == 1) //first visit
{
//common travese:
//printf("%d ",cur->value);
if(cur->value == value && *flag == NOT_FOUND)
*flag = NEXT;
else if (*flag==NEXT) {
*flag = FOUND;
printf("successor:%d\n",cur->value);
break;
}
}
if((state == 1)&&(cur->l!=NULL))
cur = cur->l;
else if((state==1)&&(cur->l==NULL))
{
state = 2;
continue;
}
else if(state==2) {
if(cur->r != NULL ) {
cur=cur->r;
state = 1;
}
else
{
if(cur->p!=NULL)
{
if(cur==cur->p->r)
state = 3;
//else state keeps 2
cur=cur->p;
}
else //cur->p==NULL
{
if(cur->p->r!=NULL)
{
cur=cur->p->r;
state = 1;
}
else
break;
//end up in lchild of root
//because root's rchild is NULL
}
}
continue;
}
else //state ==3
{
if(cur->p!=NULL)
{
if(cur==cur->p->l)
state = 2;
else
state = 3;
cur=cur->p;
continue;
}
else
break;
}
}
}
the usage is the same as the first recurrence one.
If you are confused yet,mostly about the direction of a node , you can draw a tree and draw the path of pre-order traverse on paper,it would help.
I'm not sure there are bugs left in the code,but it works well on the tree below:
0
/ \
1 2
/ \ / \
3 4 5 6
btw,"wirte down pre-order (or else) travese algorithm of a tree both by recurrence and iteration" is a common interview problem, although solving the latter by a stack is permitted.but I think the BST requirement is unnecessary in pre-order travese.
My implementation of the algorithm does not use the key. Therefore it is possible to use it in any kind of binary tree, not only in Binary search trees.
The algorith I used is this:
if given node is not present, return NULL
if node has left child, return left child
if node has right child, return right child
return right child of the closest ancestor whose right child is present and not yet processed
Bellow there is my solution.
TreeNode<ItemType>* CBinaryTree<ItemType>::succesorPreOrder(TreeNode<ItemType> *wStartNode)
{
//if given node is not present, return NULL
if (wStartNode == NULL) return NULL;
/* if node has left child, return left child */
if (wStartNode->left != NULL) return wStartNode->left;
/* if node has right child, return right child */
if (wStartNode->right != NULL) return wStartNode->right;
/* if node isLeaf
return right child of the closest ancestor whose right child is present and not yet processed*/
if (isLeaf(wStartNode)) {
TreeNode<ItemType> *cur = wStartNode;
TreeNode<ItemType> *y = wStartNode->parent;
while (y->right == NULL && y->parent!=NULL){
cur = y;
y = y->parent;
}
while (y != NULL && cur == y->right) {
cur = y;
y = y->parent;
}
return y->right;
}
}
bool CBinaryTree<ItemType>::isLeaf(TreeNode<ItemType> *wStartNode){
if (wStartNode->left == NULL && wStartNode->right == NULL) return true;
else return false;
};
Related
I want a function that traverses a binary tree with the Euler traversal (this is how it works). Of course this is easily achievable with recursion - I know how that works. But now I want to implement an iterative version of this algorithm using a stack instead of recursion. My idea was to store the direction we are traversing on the stack as well. My code is not working and I can somehow not wrap my mind around this problem. Can you give me any hints on how to tackle this issue? Here is my code so far:
#define LEFT (struct Node*) 0xBADF00D
#define RIGHT (struct Node*) 0xDEADBEEF
struct Node {
int data;
struct Node* parent;
struct Node* left;
struct Node* right;
};
void eulerTree(struct Node* root)
{
stack<struct Node*> s;
s.push(root);
s.push(RIGHT);
s.push(root);
s.push(LEFT);
while(!s.empty()) {
struct Node* direction = s.top(); s.pop();
struct Node* node = s.top(); s.pop();
visit(node);
if(direction == LEFT) {
if(node->left) {
s.push(node->left);
s.push(RIGHT);
s.push(node->left);
s.push(LEFT);
}
}
if(direction == RIGHT) {
if(node->right) {
s.push(node->right);
s.push(RIGHT);
s.push(node->right);
s.push(LEFT);
}
}
}
}
Think of a simple binary tree to start with :
1
2 3
Euler traversal for this is : 1 2 1 3 1
You see the pattern here:
root, root->left, root, root->right, root
So your stack order should be:
root
root->left
root
root->right
root
But what if your root is a leaf? then don't push anything just print the value.
Also once you push the nodes on left, right make sure you set them as 0 for the root so that you don't keep pushing them forever.
With that said, the code in cpp would be:
Edit:
The previous code I posted has a bug. The correct code is below:
void eulerTree(struct Node* root)
{
stack<struct Node*> s;
s.push(root);
while(!s.empty()) {
struct Node* node = s.pop();
visit(node);
if(node->right) {
s.push(node);
s.push(node->right);
}
if(node->left) {
s.push(node);
s.push(node->left);
}
node->left = 0;
node->right = 0;
}
}
Without destroying the tree:
But yes, even though the code is simple this destroys the tree which is not desired. To tackle this problem I am going to use two properties for leaves of the tree in a euler tree traversal.
If the leaf is left child of the parent and the right child of that parent is null
( or )
if the leaf is right child
-after this leaf is printed then print the parent nodes all the way up the root.
If the leaf is left child and the right child is not null
-after this leaf is printed then print only its immediate parent.
To illustrate look at the below tree.
1
2 3
4 5 6 7
If the leaf is 5 then after it is printed, then print all the parents upto 1.
If the leaf is 4 then after it is printed, then print just its immediate parent 2.
To simplify implementation I am going to use a parent stack in addition to the current stack.
void eulerTree(struct Node* root) {
stack<struct Node*> s;
s.push(root);
struct Node* original = root;
stack<struct Node*> p;
while(!s.empty()) {
struct Node* node = s.top();
s.pop();
visit(node);
if ( !node->right && !node->left && !p.empty() ) {
struct Node* pNode = p.top();
if ( pNode->left == node && !pNode->right || pNode->right == node ) {
while ( !p.empty() ) {
visit(p.top());
p.pop();
}
p.push(original);
} else {
visit(pNode);
}
}
if(node->left || node->right) {
p.push(node);
}
if(node->right) {
s.push(node->right);
}
if(node->left) {
s.push(node->left);
}
}
}
A recursive implementation might look like this:
void euler(Node *n) {
visit(n);
if (n->left) {
euler(n->left);
visit(n);
}
if (n->right) {
euler(n->right);
visit(n);
}
}
Now whenever this makes a recursive call, the call stack is used to remember where we are in the code and what we're doing. Then we start again at the top and when we're done, that information is popped of the stack and we continue where we left off.
If you're going to do it iteratively with your own stack, you have to do the same job yourself. You have to remember enough to continue where you left off.
We have to remember which node we were working on of course, but also there are two recursive calls so, so there are 2 possible places we might have to return to. When we return from a recursive call, then either:
We have just done the n->left call and should continue on to check n->right; OR
We have just done the n->right call and should continue with the final visit of n
We could store some extra information on the stack to distinguish these two cases, but that is not necessary for this particular algorithm. From the descriptions above, you can see that we can distinguish these cases based on the node we're returning from -- it's either n->left or n->right.
So, just storing the waiting node in the stack, we can write an iterative version like this:
int state=0; // 0 => initial visit, 1 => just did left, 2 => just did right
Node *n = root;
while (n) {
visit(n);
if (n->left && state<1) {
stack.push(n);
n=n->left;
state=0;
continue;
}
if (n->right && state<2) {
stack.push(n);
n=n->right;
state=0;
continue;
}
if (stack.empty())
break; // done
Node *child=n;
n = stack.pop();
state = (child == n->left ? 1 : 2);
}
Here is the pseudo code that wikipedia gives for iterative postorder tree traversal.
iterativePostorder(node)
parentStack = empty stack
lastnodevisited = null
while (not parentStack.isEmpty() or node ≠ null)
if (node ≠ null)
parentStack.push(node)
node = node.left
else
peeknode = parentStack.peek()
if (peeknode.right ≠ null and lastnodevisited ≠ peeknode.right)
/* if right child exists AND traversing node from left child, move right */
node = peeknode.right
else
visit(peeknode)
lastnodevisited = parentStack.pop()
It is pretty straight forward, and I have implemented it in Java. But it does not work, the problem is that every time it visits the most left leaf and return to its parent, it will add that left leaf again into the stack in next iteration. This causes an infinite loop. Is my method incorrect or the wikipedia version is wrong?
public static List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) return res;
Stack<TreeNode> s = new Stack<TreeNode>();
TreeNode lastVisitedNode = null;
TreeNode curr = root;
int i = 0;
while (curr != null || !s.isEmpty()) {
if (curr != null) {
System.out.println("push " + curr.val);
s.push(curr);
curr = curr.left;
} else {
curr = s.peek();
if (curr.right != null && lastVisitedNode != curr.right) {
curr = curr.right;
} else {
res.add(curr.val);
System.out.println("pop " + curr.val);
lastVisitedNode = s.pop();
}
}
System.out.println(s);
System.out.println(res);
if (i>8) break;
else i++;
}
return res;
}
The wikipedia version is wrong for the exact same reason as you've explained it.
Here is a probably better pseudo-code, from geeksforgeeks
1.1 Create an empty stack
2.1 Do following while root is not NULL
a) Push root's right child and then root to stack.
b) Set root as root's left child.
2.2 Pop an item from stack and set it as root.
a) If the popped item has a right child and the right child
is at top of stack, then remove the right child from stack,
push the root back and set root as root's right child.
b) Else print root's data and set root as NULL.
2.3 Repeat steps 2.1 and 2.2 while stack is not empty.
You will have to add extra code to check if the node right child is null in 2.1.a though.
The wikipedia pseudocode is not wrong. They use two different variables: node and peekNode, while you only use curr for both. Node == null refers to the case when there is no more of a left branch left to explore, so we can stop pushing and instead investigate the next element in the stack. You can either revert to using two different variables, or you make the following fix in your code:
Since you reassign curr to a non-null value everytime you investigate the stack, you need to reset curr to null after you visit your node. (Because the state that still no more left branch left to explore is still unchanged).
The wikipedia pseudocode doesn't have to do this because their node value remains null.
Here is my code which gives a perfect answer:
var currentNode = this.root()
var previousNode = null
while(!nodeStack.isEmpty() || currentNode) {
// If there is a node on which the recursive call is made, we have a subtree to explore. If this is null, we have to backtrack and do a callback.
if (currentNode) {
nodeStack.push(currentNode)
previousNode = currentNode
currentNode = currentNode.leftChild
} else {
currentNode = nodeStack.peek()
if (currentNode.rightChild && previousNode != currentNode.rightChild) {
currentNode = currentNode.rightChild
} else {
callback(currentNode)
currentNode = null
previousNode = nodeStack.pop()
}
}
}
I am a beginner to binary trees and have been working my way through the algorithms book. I have learnt about the various traversal methods of BSTs (pre-order, post order etc).
Could someone please explain how one can traverse a BST to count the number of nodes that are leaves (no children) please?
Many thanks!
Use a recursive method:
For a leaf return 1.
For a non-leaf, return the sum of that method applied to its children.
Example in PHP:
class BST {
public $left; // The substree containing the smaller entries
public $right; // The substree containing the larger entries
public $data; // The value that is stored in the node
}
function countLeafs(BST $b) {
// Test whether children exist ...
if ($b->left || $b->right) {
// ... yes, the left or the right child exists. It's not a leaf.
// Return the sum of calling countLeafs() on all children.
return ($b->left ? countLeafs($b->left) : 0)
+ ($b->right ? countLeafs($b->right) : 0);
} else {
// ... no, it's a leaf
return 1;
}
}
The different traversal methods would lead to different algorithms (although for a simple problem like this, all DFS variants are more or less the same).
I assume that you have a BST which consists of objects of type Node. A node has two fields left and right of type Node, which are the children of the node. If a child is not present, the value of that field is null. The whole tree is referenced by a reference to the root, called root. In java:
class Node {
public Node left;
public Node right;
}
Node root;
A DFS is easiest to implement by recursion: define a method
int numberOfLeafs(Node node)
which returns the number of leafs in the subtree rooted by node. Of course, numberOfLeafs(root) should yield the number of leafs of the whole tree.
As said, it is really artificial to distinguish pre-, in-, and post-order traversal here, but I'm gonna do it anyway:
Pre-order DFS: First deal with the current node, then with the children
int numberOfLeafs(Node node) {
int result = 0;
if (node.left == null && node.right == null)
result += 1;
if (node.left != null)
result += numberOfLeafs(node.left)
if (node.right != null)
result += numberOfLeafs(node.right)
return result;
}
In-order DFS: First deal with the left child, then with the current node, then with the right child
int numberOfLeafs(Node node) {
int result = 0;
if (node.left != null)
result += numberOfLeafs(node.left)
if (node.left == null && node.right == null)
result += 1;
if (node.right != null)
result += numberOfLeafs(node.right)
return result;
}
Post-order DFS: First deal with the children, then with the current node
int numberOfLeafs(Node node) {
int result = 0;
if (node.left != null)
result += numberOfLeafs(node.left)
if (node.right != null)
result += numberOfLeafs(node.right)
if (node.left == null && node.right == null)
result += 1;
return result;
}
For a BFS, you typically use a simple loop with a queue in which you add unvisited vertices. I now assume that I have a class Queue to which I can add nodes at the end and take nodes from the front:
Queue queue = new Queue();
queue.add(root);
int numberOfLeafs = 0;
while (!queue.empty) {
// take an unhandled node from the queue
Node node = queue.take();
if (node.left == null && node.right == null)
numberOfLeafs += 1;
if (node.left != null)
queue.add(node.left);
if (node.right != null)
queue.add(node.right);
}
try this
int countLeafNodes(BTNode node) {
if (node == null)
return 0;
if (node.getLeftChild() == null && node.getRightChild() == null
&& node.getParent() != null)//this is a leaf, no left or right child
return 1;
else
return countLeafNodes(node.getLeftChild())
+ countLeafNodes(node.getRightChild());
}
which recursively counts leaf nodes for left and right sub trees and returns the total count
The morris traversal works great for InOrder traversal with O(n) time and O(1) space. Is it possible to just by changing a few things achieve PreOrder and PostOrder traversal using the same algorithm.
I dont think we can Implement post order using threads .
In post order we have to traverse both the children then their parent.
We can establish a link from child to parent, but after that we cant go up this parent coz their are no links.(one points to left child and one to its right child none pointing upwards)
1
/ \
2 3
/ \
4 5
we can create a thread at 4's right node pointing to node 5 .
We can create a thread at 5's right node pointing to node 2 .
But at node 2 there are no empty pointers to create any threads. Node 2 already has its pointers pointing to node 4 & 5.
I know the solution for Preorder using morison Algo.
here is the java Code
public static void morisonPreOrder(TreeNode root) {
TreeNode curr = root, tmp=null;
while (curr != null) {
if(curr.leftNode == null) {
System.out.print(curr.value + " ");
curr = curr.rightNode;
} else {
tmp = curr.leftNode;
while (tmp.rightNode != null && tmp.rightNode != curr) {
tmp = tmp.rightNode;
}
if(tmp.rightNode == null) {
System.out.print(curr.value + " ");
tmp.rightNode = curr;
curr = curr.leftNode;
} else {
tmp.rightNode = null;
curr = curr.rightNode;
}
}
}
}
Post-order can be achieved by simply reversing the in-order Morris algorithm. To explain,
In-order python Morris implementation:
def in_order(root):
if not root:
return []
current = root
in_order_list = []
while current:
if not current.left:
in_order_list += [current.val] # Mark current as visited
current = current.right
else:
# find the right most of the left tree
predecessor = current.left
while (predecessor.right) and (predecessor.right != current):
predecessor = predecessor.right
# and create a link from this to current
if not predecessor.right:
predecessor.right = current
current = current.left
else: # now bring back the tree to it's original shape
predecessor.right = None
in_order_list += [current.val]
current = current.right
return in_order
For post-order, begin with current and if current.right is empty - start looking towards left. If not, find left most predecessor and link the left of this predecessor back to current.
(In short, flip the lefts in in-order to rights and keep inserting nodes to the beginning of the visited list ;) )
Post-order Python Morris
def post_order(root):
if not root:
return []
current = root
post_order_list = []
while current:
if not current.right:
post_order_list.insert(0, current.val)
current = current.left
else:
# find left most of the right sub-tree
predecessor = current.right
while (predecessor.left) and (predecessor.left != current):
predecessor = predecessor.left
# and create a link from this to current
if not predecessor.left:
post_order_list.insert(0, current.val)
predecessor.left = current
current = current.right
else:
predecessor.left = None
current = current.left
return post_order
Here is the sample code for pre order traversal using modified morris traversal.
You can use in a similar way to modify the right predecessor's left link for post order traversal.
I didn't get time to test the code. Please let me know if something is wrong in this code.
void preOrderNonRecursive( BSTNode* root )
{
if(!root)
return;
BSTNode* cur = root;
while(cur)
{
bool b = false;
BSTNode* pre = NULL;
if (cur->left)
{
pre = cur->left;
while(pre->right && pre->right != cur)
pre = pre->right;
if(!pre->right)
{
pre->right = cur;
b = true;
}
else
pre->right = NULL;
}
else
printf("%d\n",cur->val);
if(b)
{
printf("%d\n",cur->val);
cur = cur->left;
}
else
cur = cur->right;
}
}
/PreOrder Implementation Without stack and recursion/
private static void morrisPreorder(){
while(node != null){
System.out.println(node.getData());
if (node.getLeftNode() == null){
node = node.getRightNode();
} else {
Node rightnode = node.getRightNode();
Node current = node.getLeftNode();
while(current.getRightNode() != null && current.getRightNode().getData() != node.getData())
current = current.getRightNode();
if(current.getRightNode() == null){
current.setRightNode(node.getRightNode());
node = node.getLeftNode();
} else {
node = node.getRightNode();
}
}
}
}
The preorder traversal has been answered above.
For the postorder traversal, the answer is "Yes" as well.
The only modifications you need are:
1. When the right child of the predecessor is current node, set the right child to null and reversely output all the nodes from the left child of the current node to the predecessor.
2. Set up a dummy node and set its left child to the root of the tree.
The Java code is written here:
private void printPostTraverse(List<Integer> traverseList, TreeNode start, TreeNode end) {
TreeNode node = start;
int insertIndex = traverseList.size();
while (node != end) {
traverseList.add(insertIndex, node.val);
node = node.right;
}
traverseList.add(insertIndex, node.val);
}
public List<Integer> postorderMorrisTraversal(TreeNode root) {
List<Integer> traverseList = new ArrayList<>();
TreeNode dummy = new TreeNode(-1);
dummy.left = root;
TreeNode cur = dummy, prev = null;
while (cur != null) {
if (cur.left == null) {
cur = cur.right;
} else {
prev = cur.left;
while (prev.right != null && prev.right != cur)
prev = prev.right;
if (prev.right == null) {
prev.right = cur;
cur = cur.left;
} else {
// Modification on get the traversal list
printPostTraverse(traverseList, cur.left, prev);
prev.right = null;
cur = cur.right;
}
}
}
return traverseList;
}
How to count the number of right children in a binary tree?
This means that I only want the children marked as right.
Ex.
(Left | Right)
F(Root)
G | H
T U | I J
The right children would be U,H,and J.
What would be the algorithm to find these.
int count(Tree *r){
if(r == NULL) return 0;
int num_l=0, num_r=0;
if(r->left != NULL)
num_l = count(r->left);
if(r->right != NULL)
num_r = count(r->right)+1;
return num_l+num_r
}
In recursive approach,
You would be calling a function to traverse your tree,
for current node, you need to:
check if current node has right child (then increment the counter), and then call the function recursively for right node.
check if current node has left child, call the function recursively for left node.
This should work.
Do a simple traversal on the tree (i.e. post order, in order) and for each node do +1 if it has right child.
Example (didn't try to compile and check it):
int countRightChildren(Node root)
{
if (root == null) return 0;
int selfCount = (root.getRightChild() != null) ? 1 : 0;
return selfCount + countRightChildren(root.getLeftChild()) + countRightChildren(root.getRightChild());
}
You can do it recursively as:
If tree does not exist, there are no
R children.
If tree exists, then # R children = #
R children in R-subtree + # R
children in L-subtree
.
int countRChildren(Node *root) {
if(!root) // tree does not exist.
return 0;
// tree exists...now see if R node exits or not.
if(root->right) // right node exist
// return 1 + # of R children in L/R subtree.
return 1 + countRChildren(root->right) + countRChildren(root->left);
else // right nodes does not exist.
// total count of R children will come from left subtree.
return countRChildren(root->left);
}
This is include how i build the struct
struct Item
{
int info;
struct Item* right;
struct Item* left;
};
typedef struct Item* Node;
int countRightSons(Node tree)
{
if(!tree)
return 0;
if(tree->right != NULL)
return 1 + countRightSons(tree->right) + countRightSons(tree->left);
return countRightSons(tree->left);
}
Simple recursive approach,
check (even if not needed) for all the 4 possibilities:
left and right does not exists
left and right exists
left exists and right doesnt
right exists and left doesnt
public static int countRightChildren(BST tree) {
if (tree.root==null) return Integer.MIN_VALUE;
return countRightChildren(tree.root);}
public static int countRightChildren(Node curr) {
if (curr.right==null&&curr.left==null) return 0;
else if (curr.right!=null&&curr.left==null)
return curr.right.data+countRightChildren(curr.right);
else if (curr.right==null&&curr.left!=null)
return countRightChildren(curr.left);
else if (curr.right!=null&&curr.left!=null)
return curr.right.data+countRightChildren(curr.left)+countRightChildren(curr.right);
return Integer.MIN_VALUE;
}