I have been asked in an interviews to print the boundary of the Binary Tree. For example.
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ \
8 9 10
Answer will be : 1, 2, 4, 8, 9, 10, 7, 3
I have given the following answer.
First Method :
I have used a Bool variable to solve the above problem.
void printLeftEdges(BinaryTree *p, bool print) {
if (!p) return;
if (print || (!p->left && !p->right))
cout << p->data << " ";
printLeftEdges(p->left, print);
printLeftEdges(p->right, false);
}
void printRightEdges(BinaryTree *p, bool print) {
if (!p) return;
printRightEdges(p->left, false);
printRightEdges(p->right, print);
if (print || (!p->left && !p->right))
cout << p->data << " ";
}
void printOuterEdges(BinaryTree *root) {
if (!root) return;
cout << root->data << " ";
printLeftEdges(root->left, true);
printRightEdges(root->right, true);
}
His Response : You have used Bool variable so many times. Can you solve this without using that.
Second Method :
I simply used tree traversal to solve this problem.
1. Print the left boundary in top-down manner.
2. Print all leaf nodes from left to right, which can again be sub-divided into two sub-parts:
2.1 Print all leaf nodes of left sub-tree from left to right.
2.2 Print all leaf nodes of right subtree from left to right.
3. Print the right boundary in bottom-up manner.
His Response : He was not happy with this method too. He told that you are traversing the tree 3 times. That is too much. Give another solution if you have any.
Third Method :
This time i have went for Level Order traversal (BFS).
1: Print starting and ending node of each level
2: For each other node check if its both the children are <b>NULL</b> then print that node too.
His Response : He was not seems happy with this method too because this method takes extra memory of order O(n).
My question is that Tell me a method which traverse tree single times, do not use any Bool variable and do not use any extra memory. Is it possible?
I guess this should do the trick:
traverse(BinaryTree *root)
{
if (!root) return;
cout << p->data << " ";
if (root->left ) traverseL(root->left ); //special function for outer left
if (root->right) traverseR(root->right); //special function for outer right
}
traverseL(BinaryTree *p)
{
cout << p->data << " ";
if (root->left ) traverseL(root->left ); //still in outer left
if (root->right) traverseC(root->right);
}
traverseR(BinaryTree *p)
{
if (root->left ) traverseC(root->left );
if (root->right) traverseR(root->right); //still in outer right
cout << p->data << " ";
}
traverseC(BinaryTree *p)
{
if (!root->left && !root->right) //bottom reached
cout << p->data << " ";
else
{
if (root->left ) traverseC(root->left );
if (root->right) traverseC(root->right);
}
}
Start with the traverse function.
Got rid of the null-queries at the beginning of each method (avoids one function call at each end).
Does not need bool variables, simply uses three different traversal methods:
one for the left edge, outputting the node before traversal
one for the right edge, outputting the node after traversal
one for all other nodes, outputting the node if there are no siblings.
Below is a recursive solution in Python3 with time complexity O(n). Algorithm here is to print left most nodes from top to bottom, leaf nodes from left to right and right most nodes from bottom to top. Adding boolean flags (isLeft,isRight) for left and right tree traversal simplifies the code and drives the time complexity of O(n).
#Print tree boundary nodes
def TreeBoundry(node,isLeft,isRight):
#Left most node and leaf nodes
if(isLeft or isLeaf(node)): print(node.data,end=' ')
#Process next left node
if(node.getLeft() is not None): TreeBoundry(node.getLeft(), True,False)
#Process next right node
if(node.getRight() is not None):TreeBoundry(node.getRight(), False,True)
#Right most node
if(isRight and not isLeft and not isLeaf(node)):print(node.data,end=' ')
#Check is a node is leaf
def isLeaf(node):
if (node.getLeft() is None and node.getRight() is None):
return True
else:
return False
#Get started
#https://github.com/harishvc/challenges/blob/master/binary-tree-edge-nodes.py
TreeBoundry(root,True,True)
Method O(n) No extra space and single traversal of tree.
I divided the Tree Nodes into four types of nodes
Type 1 -> Nodes which form the left boundary(eg 8)
Type 0 -> Nodes which do not form the boundar(eg 12)
Type 3 -> Nodes which form the right boundary(eg 22)
Leaf Nodes(eg 4,10,14)
In my method i am just doing recurrsion method of tree traversal (just modified) where my function is of this form
void recFunc(btNode *temp,int type)
{
//Leaf Nodes
if((temp->left == NULL)&&(temp->right == NULL))
cout << temp->data << " ";
// type -1 Nodes must be printed before their children
else if(type == 1)cout << temp->data << " ";
else {;}
if(type == 3)
{
if(temp->left)recFunc(temp->left,0);
if(temp->right)recFunc(temp->right,3);
//type 3 nodes must be printed after their children
cout << temp->data << " ";
}
else if(type == 1)
{
if(temp->left)recFunc(temp->left,1);
if(temp->right)recFunc(temp->right,0);
}
else if(type == 0)
{
if(temp->left)recFunc(temp->left,0);
if(temp->right)recFunc(temp->right,0);
}
else {;}
}
where i have modofied the
In my recurrsive function Nodes of type 1 must make their left nodes
as type 1 and must be printed before calling their children(if they
exist)
Nodes Of Type 3 must be printed in reverse order .So they must be
printed after call to their children.They must also assign their
right children as Type 3 Nodes
Nodes Of Type 0 must not be printed and they assign their children as
type 0 Nodes
Leaf Nodes must be directly printed only and return
Link to Code
//4 diff list for 4 different part of the solution
1)left border 2)right border 3)leaf in left tree 4)leaf in right tree
public class PRintBinaryTreeBoundary {
ArrayList<TreeNode> leftBorderList=new ArrayList<>();
ArrayList<TreeNode> leftLEafNode=new ArrayList<>();
ArrayList<TreeNode> rightBorderList=new ArrayList<>();
ArrayList<TreeNode> rightLEafNode=new ArrayList<>();
public static void main(String[] args) {
// TODO Auto-generated method stub
/* 1
/ \
2 3
/ \ / \
4 5 6 7
/ \ \
8 9 10*/
TreeNode one=new TreeNode(1);
TreeNode two=new TreeNode(2);
TreeNode three=new TreeNode(3);
TreeNode four=new TreeNode(4);
TreeNode five=new TreeNode(5);
TreeNode six=new TreeNode(6);
TreeNode seven=new TreeNode(7);
TreeNode eight=new TreeNode(8);
TreeNode nine=new TreeNode(9);
TreeNode ten=new TreeNode(10);
one.left=two; one.right=three;
two.left=four;two.right=five;
three.left=six;three.right=seven;
five.left=eight;
six.right=nine;
seven.right=ten;
PRintBinaryTreeBoundary p=new PRintBinaryTreeBoundary();
p.print(one);
}
private void print(TreeNode one) {
System.out.println(one.val);
populateLeftBorderList(one.left);
populateRightBorderList(one.right);
populateLeafOfLeftTree(one.left);
populateLeafOfRightTree(one.right);
System.out.println(this.leftBorderList);
System.out.println(this.leftLEafNode);
System.out.println(this.rightLEafNode);
Collections.reverse(this.rightBorderList);
System.out.println(this.rightBorderList);
}
private void populateLeftBorderList(TreeNode node) {
TreeNode n = node;
while (n != null) {
this.leftBorderList.add(n);
n = n.left;
}
}
private void populateRightBorderList(TreeNode node) {
TreeNode n = node;
while (n != null) {
this.rightBorderList.add(n);
n = n.right;
}
}
private void populateLeafOfLeftTree(TreeNode leftnode) {
Queue<TreeNode> q = new LinkedList<>();
q.add(leftnode);
while (!q.isEmpty()) {
TreeNode n = q.remove();
if (null == n.left && null == n.right && !this.leftBorderList.contains(n)) {
leftLEafNode.add(n);
}
if (null != n.left)
q.add(n.left);
if (null != n.right)
q.add(n.right);
}
}
private void populateLeafOfRightTree(TreeNode rightNode) {
Queue<TreeNode> q = new LinkedList<>();
q.add(rightNode);
while (!q.isEmpty()) {
TreeNode n = q.remove();
if (null == n.left && null == n.right && !this.rightBorderList.contains(n)) {
rightLEafNode.add(n);
}
if (null != n.left)
q.add(n.left);
if (null != n.right)
q.add(n.right);
}
}
}
Hope this helps:
// Java program to print boundary traversal of binary tree
/* A binary tree node has data, pointer to left child
and a pointer to right child */
class Node {
int data;
Node left, right;
Node(int item)
{
data = item;
left = right = null;
}
}
class BinaryTree {
Node root;
// A simple function to print leaf nodes of a binary tree
void printLeaves(Node node)
{
if (node != null) {
printLeaves(node.left);
// Print it if it is a leaf node
if (node.left == null && node.right == null)
System.out.print(node.data + " ");
printLeaves(node.right);
}
}
// A function to print all left boundary nodes, except a leaf node.
// Print the nodes in TOP DOWN manner
void printBoundaryLeft(Node node)
{
if (node != null) {
if (node.left != null) {
// to ensure top down order, print the node
// before calling itself for left subtree
System.out.print(node.data + " ");
printBoundaryLeft(node.left);
}
else if (node.right != null) {
System.out.print(node.data + " ");
printBoundaryLeft(node.right);
}
// do nothing if it is a leaf node, this way we avoid
// duplicates in output
}
}
// A function to print all right boundary nodes, except a leaf node
// Print the nodes in BOTTOM UP manner
void printBoundaryRight(Node node)
{
if (node != null) {
if (node.right != null) {
// to ensure bottom up order, first call for right
// subtree, then print this node
printBoundaryRight(node.right);
System.out.print(node.data + " ");
}
else if (node.left != null) {
printBoundaryRight(node.left);
System.out.print(node.data + " ");
}
// do nothing if it is a leaf node, this way we avoid
// duplicates in output
}
}
// A function to do boundary traversal of a given binary tree
void printBoundary(Node node)
{
if (node != null) {
System.out.print(node.data + " ");
// Print the left boundary in top-down manner.
printBoundaryLeft(node.left);
// Print all leaf nodes
printLeaves(node.left);
printLeaves(node.right);
// Print the right boundary in bottom-up manner
printBoundaryRight(node.right);
}
}
// Driver program to test above functions
public static void main(String args[])
{
BinaryTree tree = new BinaryTree();
tree.root = new Node(20);
tree.root.left = new Node(8);
tree.root.left.left = new Node(4);
tree.root.left.right = new Node(12);
tree.root.left.right.left = new Node(10);
tree.root.left.right.right = new Node(14);
tree.root.right = new Node(22);
tree.root.right.right = new Node(25);
tree.printBoundary(tree.root);
}
}
Boundary Traversal of binary tree
Below is a Java O(n) time complexity solution that solves the problem of counting duplicates (ex: left node that is also leaf node)
class Node {
Node left;
Node right;
int data;
Node(int d) {
data = d;
left = right = null;
}
}
class BinaryTree {
Node root;
public void getBoundary() {
preorderLeft(root);
inorderLeaves(root);
postorderRight(root);
}
public boolean isLeaf(Node node) {
if (node != null && node.left == null && node.right == null) return true;
return false;
}
public void preorderLeft(Node start) {
if (start != null && isLeaf(start) == false) System.out.print(start.data + " ");
if (start.left != null) preorderLeftSide(start.left);
}
public void inorderLeaves(Node start) {
if(start == null) return;
if(start.left != null) inorderLeaves(start.left);
if(start.left == null && start.right == null) System.out.print(start.data + " ");
if(start.right != null) inorderLeaves(start.right);
}
public void postorderRight(Node start) {
if(start.right != null) postorderRightSide(start.right);
if(start != null && isLeaf(start) == false) System.out.print(start.data + " ");
}
}
This YouTube video was very helpful. The author write comments explaining each method and shows how to skip duplicates. https://youtu.be/7GzuxmZ34cI
By using vertical distance from the root node and level we can solve it using list and map.
map<int,int>tmap; #store the vertical distance and level
list<int>llist; #store the node values
void Buildfunction(root,d, l){
if(root == NULL){
return;
} else if(tmap.count(d) == 0){
tmap[d] = l;
llist.push_back(root->data);
} else if((root->left == NULL && root->right==NULL) || tmap[d] < l){
tmap[d] = l;
llist.push_back(root->data);
}
Buildfunction(root->left,d--,l++);
Buildfunction(root->right,d++,l++);
}
where d pointing to vertical distance from current node respect to root
and l pointing to level of the current node starting from 0
The following python solution worked for me. It handles all the cases.
Based on the solution of #azt
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def printLeaves(root):
if (root):
printLeaves(root.left)
if root.left is None and root.right is None:
print(root.data),
printLeaves(root.right)
def printBoundaryC(node):
if not node.left or not node.right:
print(node.data)
if node.left:
printBoundaryC(node.left)
if node.right:
printBoundaryC(node.right)
def printBoundaryLeft(root):
print(root.data)
if root.left:
printBoundaryLeft(root.left)
if root.right:
printBoundaryC(root.right)
def printBoundaryRight(root):
if root.right:
printBoundaryRight(root.right)
elif root.left:
printBoundaryC(root.left)
print(root.data)
def printBoundary(root):
if (root):
print(root.data)
if root.left:
printBoundaryLeft(root.left)
if root.right:
printBoundaryRight(root.right)
root = Node(20)
root.left = Node(8)
root.left.left = Node(4)
root.left.right = Node(12)
root.left.right.left = Node(10)
root.left.right.left.right = Node(5)
root.left.right.right = Node(14)
root.right = Node(22)
root.right.right = Node(25)
printBoundary(root)
Related
Can I implement a binary heap by only using a TreeNode inferface (has children, or left/right, or/and parent.. something like this)?
I want to not rely on using array or linked list.
If I don't use array or linked list, I have a trouble inserting the next element in the correct place & keep it a complete binary tree (all non-leaf nodes are full). Also have trouble taking out the root and re-heapifying.
One key observation is this:
The path from the root to the last leaf in a complete binary tree is represented by the binary representation of the size of the tree (number of nodes in the tree).
For instance, this tree has 9 nodes.
1
/ \
4 2
/ \ / \
6 5 3 7
/ \
9 8
9 in binary is 1001. Skipping the most significant "1", this can be read from left-to-right as 0, 0, 1 or "left-left-right". That describes indeed the path from root to the leaf node with value 8!
The same principle holds for when you need to find the insertion point for a new node. Then first increase the size, so this becomes 10 in the example. The binary representation is 1010. Skipping the first digit, this represents "left-right-left". The last direction ("left") gives information about the edge that must be added. And indeed, "left-right" leads us to the node with value 5, and a new node has to be inserted as left-child of that node!
To restore the heap property after an insertion, keep track of the path towards the newly inserted leaf (for example, when coming back out of a recursive function), and wind that path back, each time verifying the heap property, and swapping values when necessary.
Similarly, for an extraction of the root value: first find the node to delete (see above), delete that node and assign the deleted value to the root node. Then sift down the heap to restore the heap property.
Here is an implementation in plain JavaScript -- it should be easy to port this to any other language:
class Node {
constructor(value) {
this.value = value;
this.left = this.right = null;
}
swapValueWith(other) { // We don't swap nodes, just their values
let temp = this.value;
this.value = other.value;
other.value = temp;
}
}
class HeapTree {
constructor() {
this.root = null;
this.size = 0;
}
insert(value) {
this.size++;
if (this.root == null) {
this.root = new Node(value);
} else { // Use the binary representation of the size to find insertion point
this.insertRecursive(this.root, 1 << (Math.floor(Math.log2(this.size)) - 1), value);
}
}
insertRecursive(node, bit, value) {
let side = this.size & bit;
let child;
if (side > 0) {
if (bit == 1) node.right = new Node(value);
child = node.right;
} else {
if (bit == 1) node.left = new Node(value);
child = node.left;
}
if (bit > 1) this.insertRecursive(child, bit>>1, value)
if (node.value > child.value) node.swapValueWith(child); // sift up
}
extract() {
if (this.root == null) return; // Nothing to extract
let value = this.root.value; // The value to return
if (this.size == 1) {
this.root = null;
} else {
// Use the binary representation of the size to find last leaf -- to be deleted
this.root.value = this.deleteRecursive(this.root, 1 << (Math.floor(Math.log2(this.size)) - 1));
// Sift down
let node = this.root;
while (true) {
let minNode = node;
if (node.left != null && node.left.value < minNode.value) minNode = node.left;
if (node.right != null && node.right.value < minNode.value) minNode = node.right;
if (minNode === node) break;
node.swapValueWith(minNode);
node = minNode;
}
}
this.size--;
return value;
}
deleteRecursive(node, bit) {
let side = this.size & bit;
let child;
if (side > 0) {
child = node.right;
if (bit == 1) node.right = null;
} else {
child = node.left;
if (bit == 1) node.left = null;
}
return bit == 1 ? child.value : this.deleteRecursive(child, bit>>1);
}
}
// Demo
let heap = new HeapTree();
for (let value of [4,2,5,8,7,9,0,3,1,6]){
heap.insert(value);
}
// Output the values in sorted order:
while (heap.root != null) {
console.log(heap.extract());
}
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
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;
};
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;
}
This is an interview question
I think of a solution.
It uses queue.
public Void BFS()
{
Queue q = new Queue();
q.Enqueue(root);
Console.WriteLine(root.Value);
while (q.count > 0)
{
Node n = q.DeQueue();
if (n.left !=null)
{
Console.Writeln(n.left);
q.EnQueue(n.left);
}
if (n.right !=null)
{
Console.Writeln(n.right);
q.EnQueue(n.right);
}
}
}
Can anything think of better solution than this, which doesn't use Queue?
Level by level traversal is known as Breadth-first traversal. Using a Queue is the proper way to do this. If you wanted to do a depth first traversal you would use a stack.
The way you have it is not quite standard though.
Here's how it should be.
public Void BFS()
{
Queue q = new Queue();
q.Enqueue(root);//You don't need to write the root here, it will be written in the loop
while (q.count > 0)
{
Node n = q.DeQueue();
Console.Writeln(n.Value); //Only write the value when you dequeue it
if (n.left !=null)
{
q.EnQueue(n.left);//enqueue the left child
}
if (n.right !=null)
{
q.EnQueue(n.right);//enque the right child
}
}
}
Edit
Here's the algorithm at work.
Say you had a tree like so:
1
/ \
2 3
/ / \
4 5 6
First, the root (1) would be enqueued. The loop is then entered.
first item in queue (1) is dequeued and printed.
1's children are enqueued from left to right, the queue now contains {2, 3}
back to start of loop
first item in queue (2) is dequeued and printed
2's children are enqueued form left to right, the queue now contains {3, 4}
back to start of loop
...
The queue will contain these values over each loop
1: {1}
2: {2, 3}
3: {3, 4}
4: {4, 5, 6}
5: {5, 6}
6: {6}
7: {}//empty, loop terminates
Output:
1
2
3
4
5
6
Since the question requires printing the tree level by level, there should be a way to determine when to print the new line character on the console. Here's my code which tries to do the same by appending NewLine node to the queue,
void PrintByLevel(Node *root)
{
Queue q;
Node *newline = new Node("\n");
Node *v;
q->enque(root);
q->enque(newline);
while(!q->empty()) {
v = q->deque();
if(v == newline) {
printf("\n");
if(!q->empty())
q->enque(newline);
}
else {
printf("%s", v->val);
if(v->Left)
q-enque(v->left);
if(v->right)
q->enque(v->right);
}
}
delete newline;
}
Let's see some Scala solutions. First, I'll define a very basic binary tree:
case class Tree[+T](value: T, left: Option[Tree[T]], right: Option[Tree[T]])
We'll use the following tree:
1
/ \
2 3
/ / \
4 5 6
You define the tree like this:
val myTree = Tree(1,
Some(Tree(2,
Some(Tree(4, None, None)),
None
)
),
Some(Tree(3,
Some(Tree(5, None, None)),
Some(Tree(6, None, None))
)
)
)
We'll define a breadthFirst function which will traverse the tree applying the desired function to each element. With this, we'll define a print function and use it like this:
def printTree(tree: Tree[Any]) =
breadthFirst(tree, (t: Tree[Any]) => println(t.value))
printTree(myTree)
Now, Scala solution, recursive, lists but no queues:
def breadthFirst[T](t: Tree[T], f: Tree[T] => Unit): Unit = {
def traverse(trees: List[Tree[T]]): Unit = trees match {
case Nil => // do nothing
case _ =>
val children = for{tree <- trees
Some(child) <- List(tree.left, tree.right)}
yield child
trees map f
traverse(children)
}
traverse(List(t))
}
Next, Scala solution, queue, no recursion:
def breadthFirst[T](t: Tree[T], f: Tree[T] => Unit): Unit = {
import scala.collection.mutable.Queue
val queue = new Queue[Option[Tree[T]]]
import queue._
enqueue(Some(t))
while(!isEmpty)
dequeue match {
case Some(tree) =>
f(tree)
enqueue(tree.left)
enqueue(tree.right)
case None =>
}
}
That recursive solution is fully functional, though I have an uneasy feeling that it can be further simplified.
The queue version is not functional, but it is highly effective. The bit about importing an object is unusual in Scala, but put to good use here.
C++:
struct node{
string key;
struct node *left, *right;
};
void printBFS(struct node *root){
std::queue<struct node *> q;
q.push(root);
while(q.size() > 0){
int levelNodes = q.size();
while(levelNodes > 0){
struct node *p = q.front();
q.pop();
cout << " " << p->key ;
if(p->left != NULL) q.push(p->left);
if(p->right != NULL) q.push(p->right);
levelNodes--;
}
cout << endl;
}
}
Input :
Balanced tree created from:
string a[] = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n"};
Output:
g
c k
a e i m
b d f h j l n
Algorithm:
Create an ArrayList of Linked List Nodes.
Do the level order traversal using queue(Breadth First Search).
For getting all the nodes at each level, before you take out a node from queue, store the size of the queue in a variable, say you call it as levelNodes.
Now while levelNodes > 0, take out the nodes and print it and add their children into the queue.
After this while loop put a line break.
P.S: I know the OP said, no queue. My answer is just to show if someone is looking for a C++ solution using queue.
public class LevelOrderTraversalQueue {
Queue<Nodes> qe = new LinkedList<Nodes>();
public void printLevelOrder(Nodes root)
{
if(root == null) return;
qe.add(root);
int count = qe.size();
while(count!=0)
{
System.out.print(qe.peek().getValue());
System.out.print(" ");
if(qe.peek().getLeft()!=null) qe.add(qe.peek().getLeft());
if(qe.peek().getRight()!=null) qe.add(qe.peek().getRight());
qe.remove(); count = count -1;
if(count == 0 )
{
System.out.println(" ");
count = qe.size();
}
}
}
}
In order to print out by level, you can store the level information with the node as a tuple to add to the queue. Then you can print a new line whenever the level is changed. Here is a Python code to do so.
from collections import deque
class BTreeNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def printLevel(self):
""" Breadth-first traversal, print out the data by level """
level = 0
lastPrintedLevel = 0
visit = deque([])
visit.append((self, level))
while len(visit) != 0:
item = visit.popleft()
if item[1] != lastPrintedLevel: #New line for a new level
lastPrintedLevel +=1
print
print item[0].data,
if item[0].left != None:
visit.append((item[0].left, item[1] + 1))
if item[0].right != None:
visit.append((item[0].right, item[1] + 1))
Try this one (Complete code) :
class HisTree
{
public static class HisNode
{
private int data;
private HisNode left;
private HisNode right;
public HisNode() {}
public HisNode(int _data , HisNode _left , HisNode _right)
{
data = _data;
right = _right;
left = _left;
}
public HisNode(int _data)
{
data = _data;
}
}
public static int height(HisNode root)
{
if (root == null)
{
return 0;
}
else
{
return 1 + Math.max(height(root.left), height(root.right));
}
}
public static void main(String[] args)
{
// 1
// / \
// / \
// 2 3
// / \ / \
// 4 5 6 7
// /
// 21
HisNode root1 = new HisNode(3 , new HisNode(6) , new HisNode(7));
HisNode root3 = new HisNode(4 , new HisNode(21) , null);
HisNode root2 = new HisNode(2 , root3 , new HisNode(5));
HisNode root = new HisNode(1 , root2 , root1);
printByLevels(root);
}
private static void printByLevels(HisNode root) {
List<HisNode> nodes = Arrays.asList(root);
printByLevels(nodes);
}
private static void printByLevels(List<HisNode> nodes)
{
if (nodes == null || (nodes != null && nodes.size() <= 0))
{
return;
}
List <HisNode> nodeList = new LinkedList<HisNode>();
for (HisNode node : nodes)
{
if (node != null)
{
System.out.print(node.data);
System.out.print(" , ");
nodeList.add(node.left);
nodeList.add(node.right);
}
}
System.out.println();
if (nodeList != null && !CheckIfNull(nodeList))
{
printByLevels(nodeList);
}
else
{
return;
}
}
private static boolean CheckIfNull(List<HisNode> list)
{
for(HisNode elem : list)
{
if (elem != null)
{
return false;
}
}
return true;
}
}
I think what you expecting is to print the nodes at each level either separated by a space or a comma and the levels be separated by a new line. This is how I would code up the algorithm. We know that when we do a breadth-first search on a graph or tree and insert the nodes in a queue, all nodes in the queue coming out will be either at the same level as the one previous or a new level which is parent level + 1 and nothing else.
So when you are at a level keep printing out the node values and as soon as you find that the level of the node increases by 1, then you insert a new line before starting to print all the nodes at that level.
This is my code which does not use much memory and only the queue is needed for everything.
Assuming the tree starts from the root.
queue = [(root, 0)] # Store the node along with its level.
prev = 0
while queue:
node, level = queue.pop(0)
if level == prev:
print(node.val, end = "")
else:
print()
print(node.val, end = "")
if node.left:
queue.append((node.left, level + 1))
if node.right:
queue.append((node.right, level + 1))
prev = level
At the end all you need is the queue for all the processing.
I tweaked the answer so that it shows the null nodes and prints it by height.
Was actually fairly decent for testing the balance of a red black tree. can
also add the color into the print line to check black height.
Queue<node> q = new Queue<node>();
int[] arr = new int[]{1,2,4,8,16,32,64,128,256};
int i =0;
int b = 0;
int keeper = 0;
public void BFS()
{
q.Enqueue(root);
while (q.Count > 0)
{
node n = q.Dequeue();
if (i == arr[b])
{
System.Diagnostics.Debug.Write("\r\n"+"("+n.id+")");
b++;
i =0 ;
}
else {
System.Diagnostics.Debug.Write("(" + n.id + ")");
}
i++;
if (n.id != -1)
{
if (n.left != null)
{
q.Enqueue(n.left);
}
else
{
node c = new node();
c.id = -1;
c.color = 'b';
q.Enqueue(c);
}
if (n.right != null)
{
q.Enqueue(n.right);
}
else
{
node c = new node();
c.id = -1;
c.color = 'b';
q.Enqueue(c);
}
}
}
i = 0;
b = 0;
System.Diagnostics.Debug.Write("\r\n");
}
Of course you don't need to use queue. This is in python.
# Function to print level order traversal of tree
def printLevelOrder(root):
h = height(root)
for i in range(1, h+1):
printGivenLevel(root, i)
# Print nodes at a given level
def printGivenLevel(root , level):
if root is None:
return
if level == 1:
print "%d" %(root.data),
elif level > 1 :
printGivenLevel(root.left , level-1)
printGivenLevel(root.right , level-1)
""" Compute the height of a tree--the number of nodes
along the longest path from the root node down to
the farthest leaf node
"""
def height(node):
if node is None:
return 0
else :
# Compute the height of each subtree
lheight = height(node.left)
rheight = height(node.right)
return max(lheight, reight)
Try with below code.
public void printLevelOrder(TreeNode root) {
if (root == null) {
return;
}
Queue<TreeNode> nodesToVisit = new LinkedList<>();
nodesToVisit.add(root);
int count = nodesToVisit.size();
while (count != 0) {
TreeNode node = nodesToVisit.remove();
System.out.print(" " + node.data);
if (node.left != null) {
nodesToVisit.add(node.left);
}
if (node.right != null) {
nodesToVisit.add(node.right);
}
count--;
if (count == 0) {
System.out.println("");
count = nodesToVisit.size();
}
}
}
here is my answer.
//for level order traversal
func forEachLevelOrder(_ visit : (TreeNode) -> Void) {
visit(self)
var queue = Queue<TreeNode>()
children.forEach {
queue.Enqueue($0)
}
while let node = queue.Dequeue() {
visit(node)
node.children.forEach { queue.Enqueue($0)}
}
}
children is an array here that stores the children of a node.