Printing BFS (Binary Tree) in Level Order with _specific formatting_
up vote
29
down vote
favorite
To begin with, this question is not a dup of this one, but builds on it.
Taking the tree in that question as an example,
1
/
2 3
/ /
4 5 6
How would you modify your program to print it so,
1
2 3
4 5 6
rather than the general
1
2
3
4
5
6
I'm basically looking for intuitions on the most efficient way to do it - I've got a method involving appending the result to a list, and then looping through it. A more efficient way might be to store the last element in each level as it is popped, and print out a new line afterward.
Ideas?
python algorithm binary-tree breadth-first-search
add a comment |
up vote
29
down vote
favorite
To begin with, this question is not a dup of this one, but builds on it.
Taking the tree in that question as an example,
1
/
2 3
/ /
4 5 6
How would you modify your program to print it so,
1
2 3
4 5 6
rather than the general
1
2
3
4
5
6
I'm basically looking for intuitions on the most efficient way to do it - I've got a method involving appending the result to a list, and then looping through it. A more efficient way might be to store the last element in each level as it is popped, and print out a new line afterward.
Ideas?
python algorithm binary-tree breadth-first-search
depend whether you did too much or to little. too much, remove the / and of too little, use arrayindex to know depth
– Niklas Rosencrantz
Dec 12 '09 at 22:37
BTW, why was this question down voted?
– viksit
Dec 12 '09 at 22:47
@larsOn Ok, I understand the "remove every second line" comment now. But the first block is only an intuitive representation of the tree as it exists in memory. The third block shows what viksit already knows an algorithm for, and the second block what he would like to obtain instead.
– Pascal Cuoq
Dec 12 '09 at 23:12
This was a interview question to me
– Mustafa
Nov 11 '11 at 21:51
add a comment |
up vote
29
down vote
favorite
up vote
29
down vote
favorite
To begin with, this question is not a dup of this one, but builds on it.
Taking the tree in that question as an example,
1
/
2 3
/ /
4 5 6
How would you modify your program to print it so,
1
2 3
4 5 6
rather than the general
1
2
3
4
5
6
I'm basically looking for intuitions on the most efficient way to do it - I've got a method involving appending the result to a list, and then looping through it. A more efficient way might be to store the last element in each level as it is popped, and print out a new line afterward.
Ideas?
python algorithm binary-tree breadth-first-search
To begin with, this question is not a dup of this one, but builds on it.
Taking the tree in that question as an example,
1
/
2 3
/ /
4 5 6
How would you modify your program to print it so,
1
2 3
4 5 6
rather than the general
1
2
3
4
5
6
I'm basically looking for intuitions on the most efficient way to do it - I've got a method involving appending the result to a list, and then looping through it. A more efficient way might be to store the last element in each level as it is popped, and print out a new line afterward.
Ideas?
python algorithm binary-tree breadth-first-search
python algorithm binary-tree breadth-first-search
edited May 23 '17 at 12:18
Community♦
11
11
asked Dec 12 '09 at 22:04
viksit
3,34273548
3,34273548
depend whether you did too much or to little. too much, remove the / and of too little, use arrayindex to know depth
– Niklas Rosencrantz
Dec 12 '09 at 22:37
BTW, why was this question down voted?
– viksit
Dec 12 '09 at 22:47
@larsOn Ok, I understand the "remove every second line" comment now. But the first block is only an intuitive representation of the tree as it exists in memory. The third block shows what viksit already knows an algorithm for, and the second block what he would like to obtain instead.
– Pascal Cuoq
Dec 12 '09 at 23:12
This was a interview question to me
– Mustafa
Nov 11 '11 at 21:51
add a comment |
depend whether you did too much or to little. too much, remove the / and of too little, use arrayindex to know depth
– Niklas Rosencrantz
Dec 12 '09 at 22:37
BTW, why was this question down voted?
– viksit
Dec 12 '09 at 22:47
@larsOn Ok, I understand the "remove every second line" comment now. But the first block is only an intuitive representation of the tree as it exists in memory. The third block shows what viksit already knows an algorithm for, and the second block what he would like to obtain instead.
– Pascal Cuoq
Dec 12 '09 at 23:12
This was a interview question to me
– Mustafa
Nov 11 '11 at 21:51
depend whether you did too much or to little. too much, remove the / and of too little, use arrayindex to know depth
– Niklas Rosencrantz
Dec 12 '09 at 22:37
depend whether you did too much or to little. too much, remove the / and of too little, use arrayindex to know depth
– Niklas Rosencrantz
Dec 12 '09 at 22:37
BTW, why was this question down voted?
– viksit
Dec 12 '09 at 22:47
BTW, why was this question down voted?
– viksit
Dec 12 '09 at 22:47
@larsOn Ok, I understand the "remove every second line" comment now. But the first block is only an intuitive representation of the tree as it exists in memory. The third block shows what viksit already knows an algorithm for, and the second block what he would like to obtain instead.
– Pascal Cuoq
Dec 12 '09 at 23:12
@larsOn Ok, I understand the "remove every second line" comment now. But the first block is only an intuitive representation of the tree as it exists in memory. The third block shows what viksit already knows an algorithm for, and the second block what he would like to obtain instead.
– Pascal Cuoq
Dec 12 '09 at 23:12
This was a interview question to me
– Mustafa
Nov 11 '11 at 21:51
This was a interview question to me
– Mustafa
Nov 11 '11 at 21:51
add a comment |
12 Answers
12
active
oldest
votes
up vote
58
down vote
accepted
Just build one level at a time, e.g.:
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def traverse(rootnode):
thislevel = [rootnode]
while thislevel:
nextlevel = list()
for n in thislevel:
print n.value,
if n.left: nextlevel.append(n.left)
if n.right: nextlevel.append(n.right)
print
thislevel = nextlevel
t = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
traverse(t)
Edit: if you're keen to get a small saving in maximum consumed "auxiliary" memory (never having simultaneously all this level and the next level in such "auxiliary" memory), you can of course use collection.deque
instead of list
, and consume the current level as you go (via popleft
) instead of simply looping. The idea of creating one level at a time (as you consume --or iterate on-- the previous one) remains intact -- when you do need to distinguish levels, it's just more direct than using a single big deque plus auxiliary information (such as depth, or number of nodes remaining in a given level).
However, a list that is only appended to (and looped on, rather than "consumed") is quite a bit more efficient than a deque (and if you're after C++ solutions, quite similarly, a std::vector using just push_back
for building it, and a loop for then using it, is more efficient than a std::deque). Since all the producing happens first, then all the iteration (or consuming), an interesting alternative if memory is tightly constrained might be to use a list anyway to represent each level, then .reverse
it before you start consuming it (with .pop
calls) -- I don't have large trees around to check by measurement, but I suspect that this approach would still be faster (and actually less memory-consuming) than deque
(assuming that the underlying implementation of list [[or std::vector]] actually does recycle memory after a few calls to pop
[[or pop_back
]] -- and with the same assumption for deque, of course;-).
3
+1 I can see how using twovector
s for the two levels could be more efficient than using a singledeque
. Especially ifnextLevel
is moved outside thewhile
-loop and cleared instead of allocating a new one on the stack for each level (this is the C++ version I'm talking about, I've no idea how memory is managed in Python). This would also allow for very good cache utilization.
– Andreas Brinck
Dec 13 '09 at 7:35
Yes, in C++ you'd definitely want toswap
the vectors (and clear out the new one -- with the old one's contents -- right after that, if you're looping on it rather than usingpop_back
). In Python you could dothislevel[:] = nextlevel
, then if neededdel nextlevel[:]
, with similar effect (though I'm not sure the actual performance improvement would be measurable, it sure can't hurt;-).
– Alex Martelli
Dec 13 '09 at 7:43
@Alex - thanks for a great answer. The note on the iteration vs consumption of lists was quite informative!
– viksit
Dec 13 '09 at 10:15
add a comment |
up vote
9
down vote
Sounds like breadth-first traversal to me.
Breadth-first traversal is implemented with a queue. Here, simply insert in the queue a special token that indicate that a newline must be printed. Each time the token is found, print a newline and re-insert the token in the queue (at the end -- that's the definition of a queue).
Start the algorithm with a queue containing the root followed by the special newline token.
Yes, I mentioned the BFS part in the title :) I was thinking about the newline in the queue as well, but it seems wrong to intersperse formatting tokens within the queue itself.
– viksit
Dec 12 '09 at 22:14
1
@Viksit Would it be more acceptible to store the depth of each node in the queue? In that case you could simply print a newline each time the current traversal depth is increased.
– Andreas Brinck
Dec 12 '09 at 22:27
Ah, yes, "BFS"... I see what this three-letter acronym means now. Is the "S" for search? Isn't "search" always depth-first (or you built your binary tree wrong in the first place)?
– Pascal Cuoq
Dec 12 '09 at 22:31
@Andreas Nice! I was a little reluctant to mix special tokens and nodes in the queue too (but you have to do what you have to do...)
– Pascal Cuoq
Dec 12 '09 at 22:33
@Pascal I actually thought a little more and came up with a version that didn't require any extra storage whatsoever :)
– Andreas Brinck
Dec 12 '09 at 22:46
|
show 1 more comment
up vote
4
down vote
This is breadth first search, so you can use a queue and recursively do this in a simple and compact way ...
# built-in data structure we can use as a queue
from collections import deque
def print_level_order(head, queue = deque()):
if head is None:
return
print head.data
[queue.append(node) for node in [head.left, head.right] if node]
if queue:
print_level_order(queue.popleft(), queue)
clean and beautiful solution. Thanks man.
– Padvinder
Jun 3 '16 at 18:11
add a comment |
up vote
3
down vote
why not keep sentinal in queue and check when all the nodes in current level are processed.
public void printLevel(Node n) {
Queue<Integer> q = new ArrayBlockingQueue<Integer>();
Node sentinal = new Node(-1);
q.put(n);
q.put(sentinal);
while(q.size() > 0) {
n = q.poll();
System.out.println(n.value + " ");
if (n == sentinal && q.size() > 0) {
q.put(sentinal); //push at the end again for next level
System.out.println();
}
if (q.left != null) q.put(n.left);
if (q.right != null) q.put(n.right);
}
}
This answer isn't in Python
– Sam
Jun 13 '17 at 12:32
add a comment |
up vote
3
down vote
My solution is similar to Alex Martelli's, but I separate traversal of the data structure from processing the data structure. I put the meat of the code into iterLayers to keep printByLayer short and sweet.
from collections import deque
class Node:
def __init__(self, val, lc=None, rc=None):
self.val = val
self.lc = lc
self.rc = rc
def iterLayers(self):
q = deque()
q.append(self)
def layerIterator(layerSize):
for i in xrange(layerSize):
n = q.popleft()
if n.lc: q.append(n.lc)
if n.rc: q.append(n.rc)
yield n.val
while (q):
yield layerIterator(len(q))
def printByLayer(self):
for layer in self.iterLayers():
print ' '.join([str(v) for v in layer])
root = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
root.printByLayer()
which prints the following when run:
1
2 3
4 5 6
7
add a comment |
up vote
1
down vote
A simple Version based on Bread First Search, This code is applicable for graphs in general and can be used for binary trees as well.
def printBfsLevels(graph,start):
queue=[start]
path=
currLevel=1
levelMembers=1
height=[(0,start)]
childCount=0
print queue
while queue:
visNode=queue.pop(0)
if visNode not in path:
if levelMembers==0:
levelMembers=childCount
childCount=0
currLevel=currLevel+1
queue=queue+graph.get(visNode,)
if levelMembers > 0:
levelMembers=levelMembers-1
for node in graph.get(visNode,):
childCount=childCount+1
height.append((currLevel,node))
path=path+[visNode]
prevLevel=None
for v,k in sorted(height):
if prevLevel!=v:
if prevLevel!=None:
print "n"
prevLevel=v
print k,
return height
g={1: [2, 3,6], 2: [4, 5], 3: [6, 7],4:[8,9,13]}
printBfsLevels(g,1)
>>>
[1]
1
2 3 6
4 5 6 7
8 9 13
>>>
Another version based on Recursion, which is specific to binary tree
class BinTree:
"Node in a binary tree"
def __init__(self,val,leftChild=None,rightChild=None,root=None):
self.val=val
self.leftChild=leftChild
self.rightChild=rightChild
self.root=root
if not leftChild and not rightChild:
self.isExternal=True
def getChildren(self,node):
children=
if node.isExternal:
return
if node.leftChild:
children.append(node.leftChild)
if node.rightChild:
children.append(node.rightChild)
return children
@staticmethod
def createTree(tupleList):
"Creates a Binary tree Object from a given Tuple List"
Nodes={}
root=None
for item in treeRep:
if not root:
root=BinTree(item[0])
root.isExternal=False
Nodes[item[0]]=root
root.root=root
root.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=root.leftChild
root.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=root.rightChild
else:
CurrentParent=Nodes[item[0]]
CurrentParent.isExternal=False
CurrentParent.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=CurrentParent.leftChild
CurrentParent.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=CurrentParent.rightChild
root.nodeDict=Nodes
return root
def printBfsLevels(self,levels=None):
if levels==None:
levels=[self]
nextLevel=
for node in levels:
print node.val,
for node in levels:
nextLevel.extend(node.getChildren(node))
print 'n'
if nextLevel:
node.printBfsLevels(nextLevel)
## 1
## 2 3
## 4 5 6 7
## 8
treeRep = [(1,2,3),(2,4,5),(3,6,7),(4,8,None)]
tree= BinTree.createTree(treeRep)
tree.printBfsLevels()
>>>
1
2 3
4 5 6 7
8 None
add a comment |
up vote
1
down vote
Here my code prints the tree level by level as well as upside down
int counter=0;// to count the toatl no. of elments in the tree
void tree::print_treeupsidedown_levelbylevel(int *array)
{
int j=2;
int next=j;
int temp=0;
while(j<2*counter)
{
if(array[j]==0)
break;
while(array[j]!=-1)
{
j++;
}
for(int i=next,k=j-1 ;i<k; i++,k--)
{
temp=array[i];
array[i]=array[k];
array[k]=temp;
}
next=j+1;
j++;
}
for(int i=2*counter-1;i>=0;i--)
{
if(array[i]>0)
printf("%d ",array[i]);
if(array[i]==-1)
printf("n");
}
}
void tree::BFS()
{
queue<node *>p;
node *leaf=root;
int array[2*counter];
for(int i=0;i<2*counter;i++)
array[i]=0;
int count=0;
node *newline=new node; //this node helps to print a tree level by level
newline->val=0;
newline->left=NULL;
newline->right=NULL;
newline->parent=NULL;
p.push(leaf);
p.push(newline);
while(!p.empty())
{
leaf=p.front();
if(leaf==newline)
{
printf("n");
p.pop();
if(!p.empty())
p.push(newline);
array[count++]=-1;
}
else
{
cout<<leaf->val<<" ";
array[count++]=leaf->val;
if(leaf->left!=NULL)
{
p.push(leaf->left);
}
if(leaf->right!=NULL)
{
p.push(leaf->right);
}
p.pop();
}
}
delete newline;
print_treeupsidedown_levelbylevel(array);
}
Here in my code the function BFS prints the tree level by level, which also fills the data in an int array for printing the tree upside down. (note there is a bit of swapping is used while printing the tree upside down which helps to achieve our goal). If the swapping is not performed then for a tree like
8
/
1 12
/
5 9
/
4 7
/
6
o/p will be
6
7 4
9 5
12 1
8
but the o/p has to be
6
4 7
5 9
1 12
8
this the reason why swapping part was needed in that array.
That's not python
– user1767754
Oct 18 '17 at 5:50
add a comment |
up vote
1
down vote
class TNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
class BST:
def __init__(self, root):
self._root = root
def bfs(self):
list = [self._root]
while len(list) > 0:
print [e.data for e in list]
list = [e.left for e in list if e.left] +
[e.right for e in list if e.right]
bst = BST(TNode(1, TNode(2, TNode(4), TNode(5)), TNode(3, TNode(6), TNode(7))))
bst.bfs()
add a comment |
up vote
0
down vote
The following code will print each level of binary tree into new line:
public void printbylevel(node root){
int counter = 0, level = 0;
Queue<node> qu = new LinkedList<node>();
qu.add(root);
level = 1;
if(root.child1 != null)counter++;
if(root.child2 != null)counter++;
while(!qu.isEmpty()){
node temp = qu.remove();
level--;
System.out.print(temp.val);
if(level == 0 ){
System.out.println();
level = counter;
counter = 0;
}
if(temp.child1 != null){
qu.add(temp.child1);
counter++;
}
if(temp.child2 != null){
qu.add(temp.child2);
counter++;
}
}
}
add a comment |
up vote
0
down vote
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.
add a comment |
up vote
0
down vote
For those who are simply interested in visualizing binary trees (and not so much in the theory behind breadth-first search), there is a show
function in the binarytree package. Applied to the example given in the question,
from binarytree import Node, show
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.right.left = Node(5)
root.right.right = Node(6)
show(root)
which prints
1
/
2 3
/ /
4 5 6
add a comment |
up vote
-1
down vote
A version that doesn't require extra storage:
std::deque<Node> bfs;
bfs.push_back(start);
int nodesInThisLayer = 1;
int nodesInNextLayer = 0;
while (!bfs.empty()) {
Node front = bfs.front();
bfs.pop_front();
for (/*iterate over front's children*/) {
++nodesInNextLayer;
nodes.push_back(child);
}
std::cout << node.value;
if (0 == --nodesInThisLayer) {
std::cout << std::endl;
nodesInThisLayer = nodesInNextLayer;
nodesInNextLayer = 0;
} else {
std::cout << " ";
}
}
P.S. sorry for the C++ code, I'm not very fluent in Python yet.
@Andreas - nice! I was looking at a version of this algorithm where I would store the "level" or "depth" of where the loop was (so, this tree would have 3 levels). The problem I faced was how to increment this level each time. Looks like your approach of storing the depth of each element works better.
– viksit
Dec 12 '09 at 22:52
@Viksit If you look closer I only stores two extra integers, one for how many nodes are left to process in the current level and one for how many nodes are left to process in the next level (Or was this what you meant?)
– Andreas Brinck
Dec 12 '09 at 22:56
add a comment |
12 Answers
12
active
oldest
votes
12 Answers
12
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
58
down vote
accepted
Just build one level at a time, e.g.:
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def traverse(rootnode):
thislevel = [rootnode]
while thislevel:
nextlevel = list()
for n in thislevel:
print n.value,
if n.left: nextlevel.append(n.left)
if n.right: nextlevel.append(n.right)
print
thislevel = nextlevel
t = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
traverse(t)
Edit: if you're keen to get a small saving in maximum consumed "auxiliary" memory (never having simultaneously all this level and the next level in such "auxiliary" memory), you can of course use collection.deque
instead of list
, and consume the current level as you go (via popleft
) instead of simply looping. The idea of creating one level at a time (as you consume --or iterate on-- the previous one) remains intact -- when you do need to distinguish levels, it's just more direct than using a single big deque plus auxiliary information (such as depth, or number of nodes remaining in a given level).
However, a list that is only appended to (and looped on, rather than "consumed") is quite a bit more efficient than a deque (and if you're after C++ solutions, quite similarly, a std::vector using just push_back
for building it, and a loop for then using it, is more efficient than a std::deque). Since all the producing happens first, then all the iteration (or consuming), an interesting alternative if memory is tightly constrained might be to use a list anyway to represent each level, then .reverse
it before you start consuming it (with .pop
calls) -- I don't have large trees around to check by measurement, but I suspect that this approach would still be faster (and actually less memory-consuming) than deque
(assuming that the underlying implementation of list [[or std::vector]] actually does recycle memory after a few calls to pop
[[or pop_back
]] -- and with the same assumption for deque, of course;-).
3
+1 I can see how using twovector
s for the two levels could be more efficient than using a singledeque
. Especially ifnextLevel
is moved outside thewhile
-loop and cleared instead of allocating a new one on the stack for each level (this is the C++ version I'm talking about, I've no idea how memory is managed in Python). This would also allow for very good cache utilization.
– Andreas Brinck
Dec 13 '09 at 7:35
Yes, in C++ you'd definitely want toswap
the vectors (and clear out the new one -- with the old one's contents -- right after that, if you're looping on it rather than usingpop_back
). In Python you could dothislevel[:] = nextlevel
, then if neededdel nextlevel[:]
, with similar effect (though I'm not sure the actual performance improvement would be measurable, it sure can't hurt;-).
– Alex Martelli
Dec 13 '09 at 7:43
@Alex - thanks for a great answer. The note on the iteration vs consumption of lists was quite informative!
– viksit
Dec 13 '09 at 10:15
add a comment |
up vote
58
down vote
accepted
Just build one level at a time, e.g.:
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def traverse(rootnode):
thislevel = [rootnode]
while thislevel:
nextlevel = list()
for n in thislevel:
print n.value,
if n.left: nextlevel.append(n.left)
if n.right: nextlevel.append(n.right)
print
thislevel = nextlevel
t = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
traverse(t)
Edit: if you're keen to get a small saving in maximum consumed "auxiliary" memory (never having simultaneously all this level and the next level in such "auxiliary" memory), you can of course use collection.deque
instead of list
, and consume the current level as you go (via popleft
) instead of simply looping. The idea of creating one level at a time (as you consume --or iterate on-- the previous one) remains intact -- when you do need to distinguish levels, it's just more direct than using a single big deque plus auxiliary information (such as depth, or number of nodes remaining in a given level).
However, a list that is only appended to (and looped on, rather than "consumed") is quite a bit more efficient than a deque (and if you're after C++ solutions, quite similarly, a std::vector using just push_back
for building it, and a loop for then using it, is more efficient than a std::deque). Since all the producing happens first, then all the iteration (or consuming), an interesting alternative if memory is tightly constrained might be to use a list anyway to represent each level, then .reverse
it before you start consuming it (with .pop
calls) -- I don't have large trees around to check by measurement, but I suspect that this approach would still be faster (and actually less memory-consuming) than deque
(assuming that the underlying implementation of list [[or std::vector]] actually does recycle memory after a few calls to pop
[[or pop_back
]] -- and with the same assumption for deque, of course;-).
3
+1 I can see how using twovector
s for the two levels could be more efficient than using a singledeque
. Especially ifnextLevel
is moved outside thewhile
-loop and cleared instead of allocating a new one on the stack for each level (this is the C++ version I'm talking about, I've no idea how memory is managed in Python). This would also allow for very good cache utilization.
– Andreas Brinck
Dec 13 '09 at 7:35
Yes, in C++ you'd definitely want toswap
the vectors (and clear out the new one -- with the old one's contents -- right after that, if you're looping on it rather than usingpop_back
). In Python you could dothislevel[:] = nextlevel
, then if neededdel nextlevel[:]
, with similar effect (though I'm not sure the actual performance improvement would be measurable, it sure can't hurt;-).
– Alex Martelli
Dec 13 '09 at 7:43
@Alex - thanks for a great answer. The note on the iteration vs consumption of lists was quite informative!
– viksit
Dec 13 '09 at 10:15
add a comment |
up vote
58
down vote
accepted
up vote
58
down vote
accepted
Just build one level at a time, e.g.:
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def traverse(rootnode):
thislevel = [rootnode]
while thislevel:
nextlevel = list()
for n in thislevel:
print n.value,
if n.left: nextlevel.append(n.left)
if n.right: nextlevel.append(n.right)
print
thislevel = nextlevel
t = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
traverse(t)
Edit: if you're keen to get a small saving in maximum consumed "auxiliary" memory (never having simultaneously all this level and the next level in such "auxiliary" memory), you can of course use collection.deque
instead of list
, and consume the current level as you go (via popleft
) instead of simply looping. The idea of creating one level at a time (as you consume --or iterate on-- the previous one) remains intact -- when you do need to distinguish levels, it's just more direct than using a single big deque plus auxiliary information (such as depth, or number of nodes remaining in a given level).
However, a list that is only appended to (and looped on, rather than "consumed") is quite a bit more efficient than a deque (and if you're after C++ solutions, quite similarly, a std::vector using just push_back
for building it, and a loop for then using it, is more efficient than a std::deque). Since all the producing happens first, then all the iteration (or consuming), an interesting alternative if memory is tightly constrained might be to use a list anyway to represent each level, then .reverse
it before you start consuming it (with .pop
calls) -- I don't have large trees around to check by measurement, but I suspect that this approach would still be faster (and actually less memory-consuming) than deque
(assuming that the underlying implementation of list [[or std::vector]] actually does recycle memory after a few calls to pop
[[or pop_back
]] -- and with the same assumption for deque, of course;-).
Just build one level at a time, e.g.:
class Node(object):
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def traverse(rootnode):
thislevel = [rootnode]
while thislevel:
nextlevel = list()
for n in thislevel:
print n.value,
if n.left: nextlevel.append(n.left)
if n.right: nextlevel.append(n.right)
print
thislevel = nextlevel
t = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
traverse(t)
Edit: if you're keen to get a small saving in maximum consumed "auxiliary" memory (never having simultaneously all this level and the next level in such "auxiliary" memory), you can of course use collection.deque
instead of list
, and consume the current level as you go (via popleft
) instead of simply looping. The idea of creating one level at a time (as you consume --or iterate on-- the previous one) remains intact -- when you do need to distinguish levels, it's just more direct than using a single big deque plus auxiliary information (such as depth, or number of nodes remaining in a given level).
However, a list that is only appended to (and looped on, rather than "consumed") is quite a bit more efficient than a deque (and if you're after C++ solutions, quite similarly, a std::vector using just push_back
for building it, and a loop for then using it, is more efficient than a std::deque). Since all the producing happens first, then all the iteration (or consuming), an interesting alternative if memory is tightly constrained might be to use a list anyway to represent each level, then .reverse
it before you start consuming it (with .pop
calls) -- I don't have large trees around to check by measurement, but I suspect that this approach would still be faster (and actually less memory-consuming) than deque
(assuming that the underlying implementation of list [[or std::vector]] actually does recycle memory after a few calls to pop
[[or pop_back
]] -- and with the same assumption for deque, of course;-).
edited Dec 12 '09 at 23:29
answered Dec 12 '09 at 22:33
Alex Martelli
612k12210291273
612k12210291273
3
+1 I can see how using twovector
s for the two levels could be more efficient than using a singledeque
. Especially ifnextLevel
is moved outside thewhile
-loop and cleared instead of allocating a new one on the stack for each level (this is the C++ version I'm talking about, I've no idea how memory is managed in Python). This would also allow for very good cache utilization.
– Andreas Brinck
Dec 13 '09 at 7:35
Yes, in C++ you'd definitely want toswap
the vectors (and clear out the new one -- with the old one's contents -- right after that, if you're looping on it rather than usingpop_back
). In Python you could dothislevel[:] = nextlevel
, then if neededdel nextlevel[:]
, with similar effect (though I'm not sure the actual performance improvement would be measurable, it sure can't hurt;-).
– Alex Martelli
Dec 13 '09 at 7:43
@Alex - thanks for a great answer. The note on the iteration vs consumption of lists was quite informative!
– viksit
Dec 13 '09 at 10:15
add a comment |
3
+1 I can see how using twovector
s for the two levels could be more efficient than using a singledeque
. Especially ifnextLevel
is moved outside thewhile
-loop and cleared instead of allocating a new one on the stack for each level (this is the C++ version I'm talking about, I've no idea how memory is managed in Python). This would also allow for very good cache utilization.
– Andreas Brinck
Dec 13 '09 at 7:35
Yes, in C++ you'd definitely want toswap
the vectors (and clear out the new one -- with the old one's contents -- right after that, if you're looping on it rather than usingpop_back
). In Python you could dothislevel[:] = nextlevel
, then if neededdel nextlevel[:]
, with similar effect (though I'm not sure the actual performance improvement would be measurable, it sure can't hurt;-).
– Alex Martelli
Dec 13 '09 at 7:43
@Alex - thanks for a great answer. The note on the iteration vs consumption of lists was quite informative!
– viksit
Dec 13 '09 at 10:15
3
3
+1 I can see how using two
vector
s for the two levels could be more efficient than using a single deque
. Especially if nextLevel
is moved outside the while
-loop and cleared instead of allocating a new one on the stack for each level (this is the C++ version I'm talking about, I've no idea how memory is managed in Python). This would also allow for very good cache utilization.– Andreas Brinck
Dec 13 '09 at 7:35
+1 I can see how using two
vector
s for the two levels could be more efficient than using a single deque
. Especially if nextLevel
is moved outside the while
-loop and cleared instead of allocating a new one on the stack for each level (this is the C++ version I'm talking about, I've no idea how memory is managed in Python). This would also allow for very good cache utilization.– Andreas Brinck
Dec 13 '09 at 7:35
Yes, in C++ you'd definitely want to
swap
the vectors (and clear out the new one -- with the old one's contents -- right after that, if you're looping on it rather than using pop_back
). In Python you could do thislevel[:] = nextlevel
, then if needed del nextlevel[:]
, with similar effect (though I'm not sure the actual performance improvement would be measurable, it sure can't hurt;-).– Alex Martelli
Dec 13 '09 at 7:43
Yes, in C++ you'd definitely want to
swap
the vectors (and clear out the new one -- with the old one's contents -- right after that, if you're looping on it rather than using pop_back
). In Python you could do thislevel[:] = nextlevel
, then if needed del nextlevel[:]
, with similar effect (though I'm not sure the actual performance improvement would be measurable, it sure can't hurt;-).– Alex Martelli
Dec 13 '09 at 7:43
@Alex - thanks for a great answer. The note on the iteration vs consumption of lists was quite informative!
– viksit
Dec 13 '09 at 10:15
@Alex - thanks for a great answer. The note on the iteration vs consumption of lists was quite informative!
– viksit
Dec 13 '09 at 10:15
add a comment |
up vote
9
down vote
Sounds like breadth-first traversal to me.
Breadth-first traversal is implemented with a queue. Here, simply insert in the queue a special token that indicate that a newline must be printed. Each time the token is found, print a newline and re-insert the token in the queue (at the end -- that's the definition of a queue).
Start the algorithm with a queue containing the root followed by the special newline token.
Yes, I mentioned the BFS part in the title :) I was thinking about the newline in the queue as well, but it seems wrong to intersperse formatting tokens within the queue itself.
– viksit
Dec 12 '09 at 22:14
1
@Viksit Would it be more acceptible to store the depth of each node in the queue? In that case you could simply print a newline each time the current traversal depth is increased.
– Andreas Brinck
Dec 12 '09 at 22:27
Ah, yes, "BFS"... I see what this three-letter acronym means now. Is the "S" for search? Isn't "search" always depth-first (or you built your binary tree wrong in the first place)?
– Pascal Cuoq
Dec 12 '09 at 22:31
@Andreas Nice! I was a little reluctant to mix special tokens and nodes in the queue too (but you have to do what you have to do...)
– Pascal Cuoq
Dec 12 '09 at 22:33
@Pascal I actually thought a little more and came up with a version that didn't require any extra storage whatsoever :)
– Andreas Brinck
Dec 12 '09 at 22:46
|
show 1 more comment
up vote
9
down vote
Sounds like breadth-first traversal to me.
Breadth-first traversal is implemented with a queue. Here, simply insert in the queue a special token that indicate that a newline must be printed. Each time the token is found, print a newline and re-insert the token in the queue (at the end -- that's the definition of a queue).
Start the algorithm with a queue containing the root followed by the special newline token.
Yes, I mentioned the BFS part in the title :) I was thinking about the newline in the queue as well, but it seems wrong to intersperse formatting tokens within the queue itself.
– viksit
Dec 12 '09 at 22:14
1
@Viksit Would it be more acceptible to store the depth of each node in the queue? In that case you could simply print a newline each time the current traversal depth is increased.
– Andreas Brinck
Dec 12 '09 at 22:27
Ah, yes, "BFS"... I see what this three-letter acronym means now. Is the "S" for search? Isn't "search" always depth-first (or you built your binary tree wrong in the first place)?
– Pascal Cuoq
Dec 12 '09 at 22:31
@Andreas Nice! I was a little reluctant to mix special tokens and nodes in the queue too (but you have to do what you have to do...)
– Pascal Cuoq
Dec 12 '09 at 22:33
@Pascal I actually thought a little more and came up with a version that didn't require any extra storage whatsoever :)
– Andreas Brinck
Dec 12 '09 at 22:46
|
show 1 more comment
up vote
9
down vote
up vote
9
down vote
Sounds like breadth-first traversal to me.
Breadth-first traversal is implemented with a queue. Here, simply insert in the queue a special token that indicate that a newline must be printed. Each time the token is found, print a newline and re-insert the token in the queue (at the end -- that's the definition of a queue).
Start the algorithm with a queue containing the root followed by the special newline token.
Sounds like breadth-first traversal to me.
Breadth-first traversal is implemented with a queue. Here, simply insert in the queue a special token that indicate that a newline must be printed. Each time the token is found, print a newline and re-insert the token in the queue (at the end -- that's the definition of a queue).
Start the algorithm with a queue containing the root followed by the special newline token.
answered Dec 12 '09 at 22:11
Pascal Cuoq
66.5k6124227
66.5k6124227
Yes, I mentioned the BFS part in the title :) I was thinking about the newline in the queue as well, but it seems wrong to intersperse formatting tokens within the queue itself.
– viksit
Dec 12 '09 at 22:14
1
@Viksit Would it be more acceptible to store the depth of each node in the queue? In that case you could simply print a newline each time the current traversal depth is increased.
– Andreas Brinck
Dec 12 '09 at 22:27
Ah, yes, "BFS"... I see what this three-letter acronym means now. Is the "S" for search? Isn't "search" always depth-first (or you built your binary tree wrong in the first place)?
– Pascal Cuoq
Dec 12 '09 at 22:31
@Andreas Nice! I was a little reluctant to mix special tokens and nodes in the queue too (but you have to do what you have to do...)
– Pascal Cuoq
Dec 12 '09 at 22:33
@Pascal I actually thought a little more and came up with a version that didn't require any extra storage whatsoever :)
– Andreas Brinck
Dec 12 '09 at 22:46
|
show 1 more comment
Yes, I mentioned the BFS part in the title :) I was thinking about the newline in the queue as well, but it seems wrong to intersperse formatting tokens within the queue itself.
– viksit
Dec 12 '09 at 22:14
1
@Viksit Would it be more acceptible to store the depth of each node in the queue? In that case you could simply print a newline each time the current traversal depth is increased.
– Andreas Brinck
Dec 12 '09 at 22:27
Ah, yes, "BFS"... I see what this three-letter acronym means now. Is the "S" for search? Isn't "search" always depth-first (or you built your binary tree wrong in the first place)?
– Pascal Cuoq
Dec 12 '09 at 22:31
@Andreas Nice! I was a little reluctant to mix special tokens and nodes in the queue too (but you have to do what you have to do...)
– Pascal Cuoq
Dec 12 '09 at 22:33
@Pascal I actually thought a little more and came up with a version that didn't require any extra storage whatsoever :)
– Andreas Brinck
Dec 12 '09 at 22:46
Yes, I mentioned the BFS part in the title :) I was thinking about the newline in the queue as well, but it seems wrong to intersperse formatting tokens within the queue itself.
– viksit
Dec 12 '09 at 22:14
Yes, I mentioned the BFS part in the title :) I was thinking about the newline in the queue as well, but it seems wrong to intersperse formatting tokens within the queue itself.
– viksit
Dec 12 '09 at 22:14
1
1
@Viksit Would it be more acceptible to store the depth of each node in the queue? In that case you could simply print a newline each time the current traversal depth is increased.
– Andreas Brinck
Dec 12 '09 at 22:27
@Viksit Would it be more acceptible to store the depth of each node in the queue? In that case you could simply print a newline each time the current traversal depth is increased.
– Andreas Brinck
Dec 12 '09 at 22:27
Ah, yes, "BFS"... I see what this three-letter acronym means now. Is the "S" for search? Isn't "search" always depth-first (or you built your binary tree wrong in the first place)?
– Pascal Cuoq
Dec 12 '09 at 22:31
Ah, yes, "BFS"... I see what this three-letter acronym means now. Is the "S" for search? Isn't "search" always depth-first (or you built your binary tree wrong in the first place)?
– Pascal Cuoq
Dec 12 '09 at 22:31
@Andreas Nice! I was a little reluctant to mix special tokens and nodes in the queue too (but you have to do what you have to do...)
– Pascal Cuoq
Dec 12 '09 at 22:33
@Andreas Nice! I was a little reluctant to mix special tokens and nodes in the queue too (but you have to do what you have to do...)
– Pascal Cuoq
Dec 12 '09 at 22:33
@Pascal I actually thought a little more and came up with a version that didn't require any extra storage whatsoever :)
– Andreas Brinck
Dec 12 '09 at 22:46
@Pascal I actually thought a little more and came up with a version that didn't require any extra storage whatsoever :)
– Andreas Brinck
Dec 12 '09 at 22:46
|
show 1 more comment
up vote
4
down vote
This is breadth first search, so you can use a queue and recursively do this in a simple and compact way ...
# built-in data structure we can use as a queue
from collections import deque
def print_level_order(head, queue = deque()):
if head is None:
return
print head.data
[queue.append(node) for node in [head.left, head.right] if node]
if queue:
print_level_order(queue.popleft(), queue)
clean and beautiful solution. Thanks man.
– Padvinder
Jun 3 '16 at 18:11
add a comment |
up vote
4
down vote
This is breadth first search, so you can use a queue and recursively do this in a simple and compact way ...
# built-in data structure we can use as a queue
from collections import deque
def print_level_order(head, queue = deque()):
if head is None:
return
print head.data
[queue.append(node) for node in [head.left, head.right] if node]
if queue:
print_level_order(queue.popleft(), queue)
clean and beautiful solution. Thanks man.
– Padvinder
Jun 3 '16 at 18:11
add a comment |
up vote
4
down vote
up vote
4
down vote
This is breadth first search, so you can use a queue and recursively do this in a simple and compact way ...
# built-in data structure we can use as a queue
from collections import deque
def print_level_order(head, queue = deque()):
if head is None:
return
print head.data
[queue.append(node) for node in [head.left, head.right] if node]
if queue:
print_level_order(queue.popleft(), queue)
This is breadth first search, so you can use a queue and recursively do this in a simple and compact way ...
# built-in data structure we can use as a queue
from collections import deque
def print_level_order(head, queue = deque()):
if head is None:
return
print head.data
[queue.append(node) for node in [head.left, head.right] if node]
if queue:
print_level_order(queue.popleft(), queue)
answered Dec 14 '13 at 22:12
illerucis
43942
43942
clean and beautiful solution. Thanks man.
– Padvinder
Jun 3 '16 at 18:11
add a comment |
clean and beautiful solution. Thanks man.
– Padvinder
Jun 3 '16 at 18:11
clean and beautiful solution. Thanks man.
– Padvinder
Jun 3 '16 at 18:11
clean and beautiful solution. Thanks man.
– Padvinder
Jun 3 '16 at 18:11
add a comment |
up vote
3
down vote
why not keep sentinal in queue and check when all the nodes in current level are processed.
public void printLevel(Node n) {
Queue<Integer> q = new ArrayBlockingQueue<Integer>();
Node sentinal = new Node(-1);
q.put(n);
q.put(sentinal);
while(q.size() > 0) {
n = q.poll();
System.out.println(n.value + " ");
if (n == sentinal && q.size() > 0) {
q.put(sentinal); //push at the end again for next level
System.out.println();
}
if (q.left != null) q.put(n.left);
if (q.right != null) q.put(n.right);
}
}
This answer isn't in Python
– Sam
Jun 13 '17 at 12:32
add a comment |
up vote
3
down vote
why not keep sentinal in queue and check when all the nodes in current level are processed.
public void printLevel(Node n) {
Queue<Integer> q = new ArrayBlockingQueue<Integer>();
Node sentinal = new Node(-1);
q.put(n);
q.put(sentinal);
while(q.size() > 0) {
n = q.poll();
System.out.println(n.value + " ");
if (n == sentinal && q.size() > 0) {
q.put(sentinal); //push at the end again for next level
System.out.println();
}
if (q.left != null) q.put(n.left);
if (q.right != null) q.put(n.right);
}
}
This answer isn't in Python
– Sam
Jun 13 '17 at 12:32
add a comment |
up vote
3
down vote
up vote
3
down vote
why not keep sentinal in queue and check when all the nodes in current level are processed.
public void printLevel(Node n) {
Queue<Integer> q = new ArrayBlockingQueue<Integer>();
Node sentinal = new Node(-1);
q.put(n);
q.put(sentinal);
while(q.size() > 0) {
n = q.poll();
System.out.println(n.value + " ");
if (n == sentinal && q.size() > 0) {
q.put(sentinal); //push at the end again for next level
System.out.println();
}
if (q.left != null) q.put(n.left);
if (q.right != null) q.put(n.right);
}
}
why not keep sentinal in queue and check when all the nodes in current level are processed.
public void printLevel(Node n) {
Queue<Integer> q = new ArrayBlockingQueue<Integer>();
Node sentinal = new Node(-1);
q.put(n);
q.put(sentinal);
while(q.size() > 0) {
n = q.poll();
System.out.println(n.value + " ");
if (n == sentinal && q.size() > 0) {
q.put(sentinal); //push at the end again for next level
System.out.println();
}
if (q.left != null) q.put(n.left);
if (q.right != null) q.put(n.right);
}
}
edited Sep 19 '11 at 21:11
LPL
14.2k53265
14.2k53265
answered Sep 27 '10 at 17:33
Naresh
471
471
This answer isn't in Python
– Sam
Jun 13 '17 at 12:32
add a comment |
This answer isn't in Python
– Sam
Jun 13 '17 at 12:32
This answer isn't in Python
– Sam
Jun 13 '17 at 12:32
This answer isn't in Python
– Sam
Jun 13 '17 at 12:32
add a comment |
up vote
3
down vote
My solution is similar to Alex Martelli's, but I separate traversal of the data structure from processing the data structure. I put the meat of the code into iterLayers to keep printByLayer short and sweet.
from collections import deque
class Node:
def __init__(self, val, lc=None, rc=None):
self.val = val
self.lc = lc
self.rc = rc
def iterLayers(self):
q = deque()
q.append(self)
def layerIterator(layerSize):
for i in xrange(layerSize):
n = q.popleft()
if n.lc: q.append(n.lc)
if n.rc: q.append(n.rc)
yield n.val
while (q):
yield layerIterator(len(q))
def printByLayer(self):
for layer in self.iterLayers():
print ' '.join([str(v) for v in layer])
root = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
root.printByLayer()
which prints the following when run:
1
2 3
4 5 6
7
add a comment |
up vote
3
down vote
My solution is similar to Alex Martelli's, but I separate traversal of the data structure from processing the data structure. I put the meat of the code into iterLayers to keep printByLayer short and sweet.
from collections import deque
class Node:
def __init__(self, val, lc=None, rc=None):
self.val = val
self.lc = lc
self.rc = rc
def iterLayers(self):
q = deque()
q.append(self)
def layerIterator(layerSize):
for i in xrange(layerSize):
n = q.popleft()
if n.lc: q.append(n.lc)
if n.rc: q.append(n.rc)
yield n.val
while (q):
yield layerIterator(len(q))
def printByLayer(self):
for layer in self.iterLayers():
print ' '.join([str(v) for v in layer])
root = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
root.printByLayer()
which prints the following when run:
1
2 3
4 5 6
7
add a comment |
up vote
3
down vote
up vote
3
down vote
My solution is similar to Alex Martelli's, but I separate traversal of the data structure from processing the data structure. I put the meat of the code into iterLayers to keep printByLayer short and sweet.
from collections import deque
class Node:
def __init__(self, val, lc=None, rc=None):
self.val = val
self.lc = lc
self.rc = rc
def iterLayers(self):
q = deque()
q.append(self)
def layerIterator(layerSize):
for i in xrange(layerSize):
n = q.popleft()
if n.lc: q.append(n.lc)
if n.rc: q.append(n.rc)
yield n.val
while (q):
yield layerIterator(len(q))
def printByLayer(self):
for layer in self.iterLayers():
print ' '.join([str(v) for v in layer])
root = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
root.printByLayer()
which prints the following when run:
1
2 3
4 5 6
7
My solution is similar to Alex Martelli's, but I separate traversal of the data structure from processing the data structure. I put the meat of the code into iterLayers to keep printByLayer short and sweet.
from collections import deque
class Node:
def __init__(self, val, lc=None, rc=None):
self.val = val
self.lc = lc
self.rc = rc
def iterLayers(self):
q = deque()
q.append(self)
def layerIterator(layerSize):
for i in xrange(layerSize):
n = q.popleft()
if n.lc: q.append(n.lc)
if n.rc: q.append(n.rc)
yield n.val
while (q):
yield layerIterator(len(q))
def printByLayer(self):
for layer in self.iterLayers():
print ' '.join([str(v) for v in layer])
root = Node(1, Node(2, Node(4, Node(7))), Node(3, Node(5), Node(6)))
root.printByLayer()
which prints the following when run:
1
2 3
4 5 6
7
answered Jun 23 '13 at 18:29
Ben Haynor
914
914
add a comment |
add a comment |
up vote
1
down vote
A simple Version based on Bread First Search, This code is applicable for graphs in general and can be used for binary trees as well.
def printBfsLevels(graph,start):
queue=[start]
path=
currLevel=1
levelMembers=1
height=[(0,start)]
childCount=0
print queue
while queue:
visNode=queue.pop(0)
if visNode not in path:
if levelMembers==0:
levelMembers=childCount
childCount=0
currLevel=currLevel+1
queue=queue+graph.get(visNode,)
if levelMembers > 0:
levelMembers=levelMembers-1
for node in graph.get(visNode,):
childCount=childCount+1
height.append((currLevel,node))
path=path+[visNode]
prevLevel=None
for v,k in sorted(height):
if prevLevel!=v:
if prevLevel!=None:
print "n"
prevLevel=v
print k,
return height
g={1: [2, 3,6], 2: [4, 5], 3: [6, 7],4:[8,9,13]}
printBfsLevels(g,1)
>>>
[1]
1
2 3 6
4 5 6 7
8 9 13
>>>
Another version based on Recursion, which is specific to binary tree
class BinTree:
"Node in a binary tree"
def __init__(self,val,leftChild=None,rightChild=None,root=None):
self.val=val
self.leftChild=leftChild
self.rightChild=rightChild
self.root=root
if not leftChild and not rightChild:
self.isExternal=True
def getChildren(self,node):
children=
if node.isExternal:
return
if node.leftChild:
children.append(node.leftChild)
if node.rightChild:
children.append(node.rightChild)
return children
@staticmethod
def createTree(tupleList):
"Creates a Binary tree Object from a given Tuple List"
Nodes={}
root=None
for item in treeRep:
if not root:
root=BinTree(item[0])
root.isExternal=False
Nodes[item[0]]=root
root.root=root
root.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=root.leftChild
root.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=root.rightChild
else:
CurrentParent=Nodes[item[0]]
CurrentParent.isExternal=False
CurrentParent.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=CurrentParent.leftChild
CurrentParent.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=CurrentParent.rightChild
root.nodeDict=Nodes
return root
def printBfsLevels(self,levels=None):
if levels==None:
levels=[self]
nextLevel=
for node in levels:
print node.val,
for node in levels:
nextLevel.extend(node.getChildren(node))
print 'n'
if nextLevel:
node.printBfsLevels(nextLevel)
## 1
## 2 3
## 4 5 6 7
## 8
treeRep = [(1,2,3),(2,4,5),(3,6,7),(4,8,None)]
tree= BinTree.createTree(treeRep)
tree.printBfsLevels()
>>>
1
2 3
4 5 6 7
8 None
add a comment |
up vote
1
down vote
A simple Version based on Bread First Search, This code is applicable for graphs in general and can be used for binary trees as well.
def printBfsLevels(graph,start):
queue=[start]
path=
currLevel=1
levelMembers=1
height=[(0,start)]
childCount=0
print queue
while queue:
visNode=queue.pop(0)
if visNode not in path:
if levelMembers==0:
levelMembers=childCount
childCount=0
currLevel=currLevel+1
queue=queue+graph.get(visNode,)
if levelMembers > 0:
levelMembers=levelMembers-1
for node in graph.get(visNode,):
childCount=childCount+1
height.append((currLevel,node))
path=path+[visNode]
prevLevel=None
for v,k in sorted(height):
if prevLevel!=v:
if prevLevel!=None:
print "n"
prevLevel=v
print k,
return height
g={1: [2, 3,6], 2: [4, 5], 3: [6, 7],4:[8,9,13]}
printBfsLevels(g,1)
>>>
[1]
1
2 3 6
4 5 6 7
8 9 13
>>>
Another version based on Recursion, which is specific to binary tree
class BinTree:
"Node in a binary tree"
def __init__(self,val,leftChild=None,rightChild=None,root=None):
self.val=val
self.leftChild=leftChild
self.rightChild=rightChild
self.root=root
if not leftChild and not rightChild:
self.isExternal=True
def getChildren(self,node):
children=
if node.isExternal:
return
if node.leftChild:
children.append(node.leftChild)
if node.rightChild:
children.append(node.rightChild)
return children
@staticmethod
def createTree(tupleList):
"Creates a Binary tree Object from a given Tuple List"
Nodes={}
root=None
for item in treeRep:
if not root:
root=BinTree(item[0])
root.isExternal=False
Nodes[item[0]]=root
root.root=root
root.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=root.leftChild
root.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=root.rightChild
else:
CurrentParent=Nodes[item[0]]
CurrentParent.isExternal=False
CurrentParent.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=CurrentParent.leftChild
CurrentParent.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=CurrentParent.rightChild
root.nodeDict=Nodes
return root
def printBfsLevels(self,levels=None):
if levels==None:
levels=[self]
nextLevel=
for node in levels:
print node.val,
for node in levels:
nextLevel.extend(node.getChildren(node))
print 'n'
if nextLevel:
node.printBfsLevels(nextLevel)
## 1
## 2 3
## 4 5 6 7
## 8
treeRep = [(1,2,3),(2,4,5),(3,6,7),(4,8,None)]
tree= BinTree.createTree(treeRep)
tree.printBfsLevels()
>>>
1
2 3
4 5 6 7
8 None
add a comment |
up vote
1
down vote
up vote
1
down vote
A simple Version based on Bread First Search, This code is applicable for graphs in general and can be used for binary trees as well.
def printBfsLevels(graph,start):
queue=[start]
path=
currLevel=1
levelMembers=1
height=[(0,start)]
childCount=0
print queue
while queue:
visNode=queue.pop(0)
if visNode not in path:
if levelMembers==0:
levelMembers=childCount
childCount=0
currLevel=currLevel+1
queue=queue+graph.get(visNode,)
if levelMembers > 0:
levelMembers=levelMembers-1
for node in graph.get(visNode,):
childCount=childCount+1
height.append((currLevel,node))
path=path+[visNode]
prevLevel=None
for v,k in sorted(height):
if prevLevel!=v:
if prevLevel!=None:
print "n"
prevLevel=v
print k,
return height
g={1: [2, 3,6], 2: [4, 5], 3: [6, 7],4:[8,9,13]}
printBfsLevels(g,1)
>>>
[1]
1
2 3 6
4 5 6 7
8 9 13
>>>
Another version based on Recursion, which is specific to binary tree
class BinTree:
"Node in a binary tree"
def __init__(self,val,leftChild=None,rightChild=None,root=None):
self.val=val
self.leftChild=leftChild
self.rightChild=rightChild
self.root=root
if not leftChild and not rightChild:
self.isExternal=True
def getChildren(self,node):
children=
if node.isExternal:
return
if node.leftChild:
children.append(node.leftChild)
if node.rightChild:
children.append(node.rightChild)
return children
@staticmethod
def createTree(tupleList):
"Creates a Binary tree Object from a given Tuple List"
Nodes={}
root=None
for item in treeRep:
if not root:
root=BinTree(item[0])
root.isExternal=False
Nodes[item[0]]=root
root.root=root
root.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=root.leftChild
root.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=root.rightChild
else:
CurrentParent=Nodes[item[0]]
CurrentParent.isExternal=False
CurrentParent.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=CurrentParent.leftChild
CurrentParent.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=CurrentParent.rightChild
root.nodeDict=Nodes
return root
def printBfsLevels(self,levels=None):
if levels==None:
levels=[self]
nextLevel=
for node in levels:
print node.val,
for node in levels:
nextLevel.extend(node.getChildren(node))
print 'n'
if nextLevel:
node.printBfsLevels(nextLevel)
## 1
## 2 3
## 4 5 6 7
## 8
treeRep = [(1,2,3),(2,4,5),(3,6,7),(4,8,None)]
tree= BinTree.createTree(treeRep)
tree.printBfsLevels()
>>>
1
2 3
4 5 6 7
8 None
A simple Version based on Bread First Search, This code is applicable for graphs in general and can be used for binary trees as well.
def printBfsLevels(graph,start):
queue=[start]
path=
currLevel=1
levelMembers=1
height=[(0,start)]
childCount=0
print queue
while queue:
visNode=queue.pop(0)
if visNode not in path:
if levelMembers==0:
levelMembers=childCount
childCount=0
currLevel=currLevel+1
queue=queue+graph.get(visNode,)
if levelMembers > 0:
levelMembers=levelMembers-1
for node in graph.get(visNode,):
childCount=childCount+1
height.append((currLevel,node))
path=path+[visNode]
prevLevel=None
for v,k in sorted(height):
if prevLevel!=v:
if prevLevel!=None:
print "n"
prevLevel=v
print k,
return height
g={1: [2, 3,6], 2: [4, 5], 3: [6, 7],4:[8,9,13]}
printBfsLevels(g,1)
>>>
[1]
1
2 3 6
4 5 6 7
8 9 13
>>>
Another version based on Recursion, which is specific to binary tree
class BinTree:
"Node in a binary tree"
def __init__(self,val,leftChild=None,rightChild=None,root=None):
self.val=val
self.leftChild=leftChild
self.rightChild=rightChild
self.root=root
if not leftChild and not rightChild:
self.isExternal=True
def getChildren(self,node):
children=
if node.isExternal:
return
if node.leftChild:
children.append(node.leftChild)
if node.rightChild:
children.append(node.rightChild)
return children
@staticmethod
def createTree(tupleList):
"Creates a Binary tree Object from a given Tuple List"
Nodes={}
root=None
for item in treeRep:
if not root:
root=BinTree(item[0])
root.isExternal=False
Nodes[item[0]]=root
root.root=root
root.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=root.leftChild
root.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=root.rightChild
else:
CurrentParent=Nodes[item[0]]
CurrentParent.isExternal=False
CurrentParent.leftChild=BinTree(item[1],root=root)
Nodes[item[1]]=CurrentParent.leftChild
CurrentParent.rightChild=BinTree(item[2],root=root)
Nodes[item[2]]=CurrentParent.rightChild
root.nodeDict=Nodes
return root
def printBfsLevels(self,levels=None):
if levels==None:
levels=[self]
nextLevel=
for node in levels:
print node.val,
for node in levels:
nextLevel.extend(node.getChildren(node))
print 'n'
if nextLevel:
node.printBfsLevels(nextLevel)
## 1
## 2 3
## 4 5 6 7
## 8
treeRep = [(1,2,3),(2,4,5),(3,6,7),(4,8,None)]
tree= BinTree.createTree(treeRep)
tree.printBfsLevels()
>>>
1
2 3
4 5 6 7
8 None
edited Sep 28 '11 at 12:05
answered Sep 22 '11 at 11:51
vumaasha
1,20231631
1,20231631
add a comment |
add a comment |
up vote
1
down vote
Here my code prints the tree level by level as well as upside down
int counter=0;// to count the toatl no. of elments in the tree
void tree::print_treeupsidedown_levelbylevel(int *array)
{
int j=2;
int next=j;
int temp=0;
while(j<2*counter)
{
if(array[j]==0)
break;
while(array[j]!=-1)
{
j++;
}
for(int i=next,k=j-1 ;i<k; i++,k--)
{
temp=array[i];
array[i]=array[k];
array[k]=temp;
}
next=j+1;
j++;
}
for(int i=2*counter-1;i>=0;i--)
{
if(array[i]>0)
printf("%d ",array[i]);
if(array[i]==-1)
printf("n");
}
}
void tree::BFS()
{
queue<node *>p;
node *leaf=root;
int array[2*counter];
for(int i=0;i<2*counter;i++)
array[i]=0;
int count=0;
node *newline=new node; //this node helps to print a tree level by level
newline->val=0;
newline->left=NULL;
newline->right=NULL;
newline->parent=NULL;
p.push(leaf);
p.push(newline);
while(!p.empty())
{
leaf=p.front();
if(leaf==newline)
{
printf("n");
p.pop();
if(!p.empty())
p.push(newline);
array[count++]=-1;
}
else
{
cout<<leaf->val<<" ";
array[count++]=leaf->val;
if(leaf->left!=NULL)
{
p.push(leaf->left);
}
if(leaf->right!=NULL)
{
p.push(leaf->right);
}
p.pop();
}
}
delete newline;
print_treeupsidedown_levelbylevel(array);
}
Here in my code the function BFS prints the tree level by level, which also fills the data in an int array for printing the tree upside down. (note there is a bit of swapping is used while printing the tree upside down which helps to achieve our goal). If the swapping is not performed then for a tree like
8
/
1 12
/
5 9
/
4 7
/
6
o/p will be
6
7 4
9 5
12 1
8
but the o/p has to be
6
4 7
5 9
1 12
8
this the reason why swapping part was needed in that array.
That's not python
– user1767754
Oct 18 '17 at 5:50
add a comment |
up vote
1
down vote
Here my code prints the tree level by level as well as upside down
int counter=0;// to count the toatl no. of elments in the tree
void tree::print_treeupsidedown_levelbylevel(int *array)
{
int j=2;
int next=j;
int temp=0;
while(j<2*counter)
{
if(array[j]==0)
break;
while(array[j]!=-1)
{
j++;
}
for(int i=next,k=j-1 ;i<k; i++,k--)
{
temp=array[i];
array[i]=array[k];
array[k]=temp;
}
next=j+1;
j++;
}
for(int i=2*counter-1;i>=0;i--)
{
if(array[i]>0)
printf("%d ",array[i]);
if(array[i]==-1)
printf("n");
}
}
void tree::BFS()
{
queue<node *>p;
node *leaf=root;
int array[2*counter];
for(int i=0;i<2*counter;i++)
array[i]=0;
int count=0;
node *newline=new node; //this node helps to print a tree level by level
newline->val=0;
newline->left=NULL;
newline->right=NULL;
newline->parent=NULL;
p.push(leaf);
p.push(newline);
while(!p.empty())
{
leaf=p.front();
if(leaf==newline)
{
printf("n");
p.pop();
if(!p.empty())
p.push(newline);
array[count++]=-1;
}
else
{
cout<<leaf->val<<" ";
array[count++]=leaf->val;
if(leaf->left!=NULL)
{
p.push(leaf->left);
}
if(leaf->right!=NULL)
{
p.push(leaf->right);
}
p.pop();
}
}
delete newline;
print_treeupsidedown_levelbylevel(array);
}
Here in my code the function BFS prints the tree level by level, which also fills the data in an int array for printing the tree upside down. (note there is a bit of swapping is used while printing the tree upside down which helps to achieve our goal). If the swapping is not performed then for a tree like
8
/
1 12
/
5 9
/
4 7
/
6
o/p will be
6
7 4
9 5
12 1
8
but the o/p has to be
6
4 7
5 9
1 12
8
this the reason why swapping part was needed in that array.
That's not python
– user1767754
Oct 18 '17 at 5:50
add a comment |
up vote
1
down vote
up vote
1
down vote
Here my code prints the tree level by level as well as upside down
int counter=0;// to count the toatl no. of elments in the tree
void tree::print_treeupsidedown_levelbylevel(int *array)
{
int j=2;
int next=j;
int temp=0;
while(j<2*counter)
{
if(array[j]==0)
break;
while(array[j]!=-1)
{
j++;
}
for(int i=next,k=j-1 ;i<k; i++,k--)
{
temp=array[i];
array[i]=array[k];
array[k]=temp;
}
next=j+1;
j++;
}
for(int i=2*counter-1;i>=0;i--)
{
if(array[i]>0)
printf("%d ",array[i]);
if(array[i]==-1)
printf("n");
}
}
void tree::BFS()
{
queue<node *>p;
node *leaf=root;
int array[2*counter];
for(int i=0;i<2*counter;i++)
array[i]=0;
int count=0;
node *newline=new node; //this node helps to print a tree level by level
newline->val=0;
newline->left=NULL;
newline->right=NULL;
newline->parent=NULL;
p.push(leaf);
p.push(newline);
while(!p.empty())
{
leaf=p.front();
if(leaf==newline)
{
printf("n");
p.pop();
if(!p.empty())
p.push(newline);
array[count++]=-1;
}
else
{
cout<<leaf->val<<" ";
array[count++]=leaf->val;
if(leaf->left!=NULL)
{
p.push(leaf->left);
}
if(leaf->right!=NULL)
{
p.push(leaf->right);
}
p.pop();
}
}
delete newline;
print_treeupsidedown_levelbylevel(array);
}
Here in my code the function BFS prints the tree level by level, which also fills the data in an int array for printing the tree upside down. (note there is a bit of swapping is used while printing the tree upside down which helps to achieve our goal). If the swapping is not performed then for a tree like
8
/
1 12
/
5 9
/
4 7
/
6
o/p will be
6
7 4
9 5
12 1
8
but the o/p has to be
6
4 7
5 9
1 12
8
this the reason why swapping part was needed in that array.
Here my code prints the tree level by level as well as upside down
int counter=0;// to count the toatl no. of elments in the tree
void tree::print_treeupsidedown_levelbylevel(int *array)
{
int j=2;
int next=j;
int temp=0;
while(j<2*counter)
{
if(array[j]==0)
break;
while(array[j]!=-1)
{
j++;
}
for(int i=next,k=j-1 ;i<k; i++,k--)
{
temp=array[i];
array[i]=array[k];
array[k]=temp;
}
next=j+1;
j++;
}
for(int i=2*counter-1;i>=0;i--)
{
if(array[i]>0)
printf("%d ",array[i]);
if(array[i]==-1)
printf("n");
}
}
void tree::BFS()
{
queue<node *>p;
node *leaf=root;
int array[2*counter];
for(int i=0;i<2*counter;i++)
array[i]=0;
int count=0;
node *newline=new node; //this node helps to print a tree level by level
newline->val=0;
newline->left=NULL;
newline->right=NULL;
newline->parent=NULL;
p.push(leaf);
p.push(newline);
while(!p.empty())
{
leaf=p.front();
if(leaf==newline)
{
printf("n");
p.pop();
if(!p.empty())
p.push(newline);
array[count++]=-1;
}
else
{
cout<<leaf->val<<" ";
array[count++]=leaf->val;
if(leaf->left!=NULL)
{
p.push(leaf->left);
}
if(leaf->right!=NULL)
{
p.push(leaf->right);
}
p.pop();
}
}
delete newline;
print_treeupsidedown_levelbylevel(array);
}
Here in my code the function BFS prints the tree level by level, which also fills the data in an int array for printing the tree upside down. (note there is a bit of swapping is used while printing the tree upside down which helps to achieve our goal). If the swapping is not performed then for a tree like
8
/
1 12
/
5 9
/
4 7
/
6
o/p will be
6
7 4
9 5
12 1
8
but the o/p has to be
6
4 7
5 9
1 12
8
this the reason why swapping part was needed in that array.
edited Feb 24 '13 at 11:09
Rock
1,07072538
1,07072538
answered Nov 12 '12 at 13:24
Sumit Kumar Saha
4861921
4861921
That's not python
– user1767754
Oct 18 '17 at 5:50
add a comment |
That's not python
– user1767754
Oct 18 '17 at 5:50
That's not python
– user1767754
Oct 18 '17 at 5:50
That's not python
– user1767754
Oct 18 '17 at 5:50
add a comment |
up vote
1
down vote
class TNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
class BST:
def __init__(self, root):
self._root = root
def bfs(self):
list = [self._root]
while len(list) > 0:
print [e.data for e in list]
list = [e.left for e in list if e.left] +
[e.right for e in list if e.right]
bst = BST(TNode(1, TNode(2, TNode(4), TNode(5)), TNode(3, TNode(6), TNode(7))))
bst.bfs()
add a comment |
up vote
1
down vote
class TNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
class BST:
def __init__(self, root):
self._root = root
def bfs(self):
list = [self._root]
while len(list) > 0:
print [e.data for e in list]
list = [e.left for e in list if e.left] +
[e.right for e in list if e.right]
bst = BST(TNode(1, TNode(2, TNode(4), TNode(5)), TNode(3, TNode(6), TNode(7))))
bst.bfs()
add a comment |
up vote
1
down vote
up vote
1
down vote
class TNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
class BST:
def __init__(self, root):
self._root = root
def bfs(self):
list = [self._root]
while len(list) > 0:
print [e.data for e in list]
list = [e.left for e in list if e.left] +
[e.right for e in list if e.right]
bst = BST(TNode(1, TNode(2, TNode(4), TNode(5)), TNode(3, TNode(6), TNode(7))))
bst.bfs()
class TNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
class BST:
def __init__(self, root):
self._root = root
def bfs(self):
list = [self._root]
while len(list) > 0:
print [e.data for e in list]
list = [e.left for e in list if e.left] +
[e.right for e in list if e.right]
bst = BST(TNode(1, TNode(2, TNode(4), TNode(5)), TNode(3, TNode(6), TNode(7))))
bst.bfs()
edited Jun 30 '14 at 23:02
librik
3,39011420
3,39011420
answered Jun 30 '14 at 2:28
Swapneel Patil
2,0931126
2,0931126
add a comment |
add a comment |
up vote
0
down vote
The following code will print each level of binary tree into new line:
public void printbylevel(node root){
int counter = 0, level = 0;
Queue<node> qu = new LinkedList<node>();
qu.add(root);
level = 1;
if(root.child1 != null)counter++;
if(root.child2 != null)counter++;
while(!qu.isEmpty()){
node temp = qu.remove();
level--;
System.out.print(temp.val);
if(level == 0 ){
System.out.println();
level = counter;
counter = 0;
}
if(temp.child1 != null){
qu.add(temp.child1);
counter++;
}
if(temp.child2 != null){
qu.add(temp.child2);
counter++;
}
}
}
add a comment |
up vote
0
down vote
The following code will print each level of binary tree into new line:
public void printbylevel(node root){
int counter = 0, level = 0;
Queue<node> qu = new LinkedList<node>();
qu.add(root);
level = 1;
if(root.child1 != null)counter++;
if(root.child2 != null)counter++;
while(!qu.isEmpty()){
node temp = qu.remove();
level--;
System.out.print(temp.val);
if(level == 0 ){
System.out.println();
level = counter;
counter = 0;
}
if(temp.child1 != null){
qu.add(temp.child1);
counter++;
}
if(temp.child2 != null){
qu.add(temp.child2);
counter++;
}
}
}
add a comment |
up vote
0
down vote
up vote
0
down vote
The following code will print each level of binary tree into new line:
public void printbylevel(node root){
int counter = 0, level = 0;
Queue<node> qu = new LinkedList<node>();
qu.add(root);
level = 1;
if(root.child1 != null)counter++;
if(root.child2 != null)counter++;
while(!qu.isEmpty()){
node temp = qu.remove();
level--;
System.out.print(temp.val);
if(level == 0 ){
System.out.println();
level = counter;
counter = 0;
}
if(temp.child1 != null){
qu.add(temp.child1);
counter++;
}
if(temp.child2 != null){
qu.add(temp.child2);
counter++;
}
}
}
The following code will print each level of binary tree into new line:
public void printbylevel(node root){
int counter = 0, level = 0;
Queue<node> qu = new LinkedList<node>();
qu.add(root);
level = 1;
if(root.child1 != null)counter++;
if(root.child2 != null)counter++;
while(!qu.isEmpty()){
node temp = qu.remove();
level--;
System.out.print(temp.val);
if(level == 0 ){
System.out.println();
level = counter;
counter = 0;
}
if(temp.child1 != null){
qu.add(temp.child1);
counter++;
}
if(temp.child2 != null){
qu.add(temp.child2);
counter++;
}
}
}
edited Nov 28 '12 at 5:16
answered Nov 28 '12 at 4:50
Ramy
68138
68138
add a comment |
add a comment |
up vote
0
down vote
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.
add a comment |
up vote
0
down vote
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.
add a comment |
up vote
0
down vote
up vote
0
down vote
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 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.
answered Jul 6 at 15:35
Ankur Kothari
6515
6515
add a comment |
add a comment |
up vote
0
down vote
For those who are simply interested in visualizing binary trees (and not so much in the theory behind breadth-first search), there is a show
function in the binarytree package. Applied to the example given in the question,
from binarytree import Node, show
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.right.left = Node(5)
root.right.right = Node(6)
show(root)
which prints
1
/
2 3
/ /
4 5 6
add a comment |
up vote
0
down vote
For those who are simply interested in visualizing binary trees (and not so much in the theory behind breadth-first search), there is a show
function in the binarytree package. Applied to the example given in the question,
from binarytree import Node, show
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.right.left = Node(5)
root.right.right = Node(6)
show(root)
which prints
1
/
2 3
/ /
4 5 6
add a comment |
up vote
0
down vote
up vote
0
down vote
For those who are simply interested in visualizing binary trees (and not so much in the theory behind breadth-first search), there is a show
function in the binarytree package. Applied to the example given in the question,
from binarytree import Node, show
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.right.left = Node(5)
root.right.right = Node(6)
show(root)
which prints
1
/
2 3
/ /
4 5 6
For those who are simply interested in visualizing binary trees (and not so much in the theory behind breadth-first search), there is a show
function in the binarytree package. Applied to the example given in the question,
from binarytree import Node, show
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.right.left = Node(5)
root.right.right = Node(6)
show(root)
which prints
1
/
2 3
/ /
4 5 6
edited Nov 11 at 4:03
rassar
2,2081928
2,2081928
answered Aug 25 '17 at 9:43
Kurt Peek
8,7841765132
8,7841765132
add a comment |
add a comment |
up vote
-1
down vote
A version that doesn't require extra storage:
std::deque<Node> bfs;
bfs.push_back(start);
int nodesInThisLayer = 1;
int nodesInNextLayer = 0;
while (!bfs.empty()) {
Node front = bfs.front();
bfs.pop_front();
for (/*iterate over front's children*/) {
++nodesInNextLayer;
nodes.push_back(child);
}
std::cout << node.value;
if (0 == --nodesInThisLayer) {
std::cout << std::endl;
nodesInThisLayer = nodesInNextLayer;
nodesInNextLayer = 0;
} else {
std::cout << " ";
}
}
P.S. sorry for the C++ code, I'm not very fluent in Python yet.
@Andreas - nice! I was looking at a version of this algorithm where I would store the "level" or "depth" of where the loop was (so, this tree would have 3 levels). The problem I faced was how to increment this level each time. Looks like your approach of storing the depth of each element works better.
– viksit
Dec 12 '09 at 22:52
@Viksit If you look closer I only stores two extra integers, one for how many nodes are left to process in the current level and one for how many nodes are left to process in the next level (Or was this what you meant?)
– Andreas Brinck
Dec 12 '09 at 22:56
add a comment |
up vote
-1
down vote
A version that doesn't require extra storage:
std::deque<Node> bfs;
bfs.push_back(start);
int nodesInThisLayer = 1;
int nodesInNextLayer = 0;
while (!bfs.empty()) {
Node front = bfs.front();
bfs.pop_front();
for (/*iterate over front's children*/) {
++nodesInNextLayer;
nodes.push_back(child);
}
std::cout << node.value;
if (0 == --nodesInThisLayer) {
std::cout << std::endl;
nodesInThisLayer = nodesInNextLayer;
nodesInNextLayer = 0;
} else {
std::cout << " ";
}
}
P.S. sorry for the C++ code, I'm not very fluent in Python yet.
@Andreas - nice! I was looking at a version of this algorithm where I would store the "level" or "depth" of where the loop was (so, this tree would have 3 levels). The problem I faced was how to increment this level each time. Looks like your approach of storing the depth of each element works better.
– viksit
Dec 12 '09 at 22:52
@Viksit If you look closer I only stores two extra integers, one for how many nodes are left to process in the current level and one for how many nodes are left to process in the next level (Or was this what you meant?)
– Andreas Brinck
Dec 12 '09 at 22:56
add a comment |
up vote
-1
down vote
up vote
-1
down vote
A version that doesn't require extra storage:
std::deque<Node> bfs;
bfs.push_back(start);
int nodesInThisLayer = 1;
int nodesInNextLayer = 0;
while (!bfs.empty()) {
Node front = bfs.front();
bfs.pop_front();
for (/*iterate over front's children*/) {
++nodesInNextLayer;
nodes.push_back(child);
}
std::cout << node.value;
if (0 == --nodesInThisLayer) {
std::cout << std::endl;
nodesInThisLayer = nodesInNextLayer;
nodesInNextLayer = 0;
} else {
std::cout << " ";
}
}
P.S. sorry for the C++ code, I'm not very fluent in Python yet.
A version that doesn't require extra storage:
std::deque<Node> bfs;
bfs.push_back(start);
int nodesInThisLayer = 1;
int nodesInNextLayer = 0;
while (!bfs.empty()) {
Node front = bfs.front();
bfs.pop_front();
for (/*iterate over front's children*/) {
++nodesInNextLayer;
nodes.push_back(child);
}
std::cout << node.value;
if (0 == --nodesInThisLayer) {
std::cout << std::endl;
nodesInThisLayer = nodesInNextLayer;
nodesInNextLayer = 0;
} else {
std::cout << " ";
}
}
P.S. sorry for the C++ code, I'm not very fluent in Python yet.
edited Dec 13 '09 at 7:05
answered Dec 12 '09 at 22:37
Andreas Brinck
37.3k1371106
37.3k1371106
@Andreas - nice! I was looking at a version of this algorithm where I would store the "level" or "depth" of where the loop was (so, this tree would have 3 levels). The problem I faced was how to increment this level each time. Looks like your approach of storing the depth of each element works better.
– viksit
Dec 12 '09 at 22:52
@Viksit If you look closer I only stores two extra integers, one for how many nodes are left to process in the current level and one for how many nodes are left to process in the next level (Or was this what you meant?)
– Andreas Brinck
Dec 12 '09 at 22:56
add a comment |
@Andreas - nice! I was looking at a version of this algorithm where I would store the "level" or "depth" of where the loop was (so, this tree would have 3 levels). The problem I faced was how to increment this level each time. Looks like your approach of storing the depth of each element works better.
– viksit
Dec 12 '09 at 22:52
@Viksit If you look closer I only stores two extra integers, one for how many nodes are left to process in the current level and one for how many nodes are left to process in the next level (Or was this what you meant?)
– Andreas Brinck
Dec 12 '09 at 22:56
@Andreas - nice! I was looking at a version of this algorithm where I would store the "level" or "depth" of where the loop was (so, this tree would have 3 levels). The problem I faced was how to increment this level each time. Looks like your approach of storing the depth of each element works better.
– viksit
Dec 12 '09 at 22:52
@Andreas - nice! I was looking at a version of this algorithm where I would store the "level" or "depth" of where the loop was (so, this tree would have 3 levels). The problem I faced was how to increment this level each time. Looks like your approach of storing the depth of each element works better.
– viksit
Dec 12 '09 at 22:52
@Viksit If you look closer I only stores two extra integers, one for how many nodes are left to process in the current level and one for how many nodes are left to process in the next level (Or was this what you meant?)
– Andreas Brinck
Dec 12 '09 at 22:56
@Viksit If you look closer I only stores two extra integers, one for how many nodes are left to process in the current level and one for how many nodes are left to process in the next level (Or was this what you meant?)
– Andreas Brinck
Dec 12 '09 at 22:56
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f1894846%2fprinting-bfs-binary-tree-in-level-order-with-specific-formatting%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
depend whether you did too much or to little. too much, remove the / and of too little, use arrayindex to know depth
– Niklas Rosencrantz
Dec 12 '09 at 22:37
BTW, why was this question down voted?
– viksit
Dec 12 '09 at 22:47
@larsOn Ok, I understand the "remove every second line" comment now. But the first block is only an intuitive representation of the tree as it exists in memory. The third block shows what viksit already knows an algorithm for, and the second block what he would like to obtain instead.
– Pascal Cuoq
Dec 12 '09 at 23:12
This was a interview question to me
– Mustafa
Nov 11 '11 at 21:51