Graphviz General Tree - python

I can't render the whole Tree using graphviz. I am using DFS traversal. Renderd png only consits of root and 2 children of root, while the others are missing.
class TreeNode:
value: Any
children: List['TreeNode']
def __init__(self, value:Any)->None:
self.value=value
self.children=[]
def show(self):
dot=graphviz.Digraph("Tree",format="png")
dot.node(str(self),str(self.value))
if len(self.children) != 0:
for child in self.children:
dot.node(str(child),str(child.value))
dot.edge(str(self),str(child))
child.show()
dot.render(directory='doctest-output').replace('\\', '/')

I figured it out. Just had to pass dot as an argument. Here's code
def show(self,dot=None):
if dot is None:
dot=graphviz.Digraph("Tree",format="png")
dot.node(str(self),str(self.value))
if len(self.children) != 0:
for child in self.children:
dot.node(str(child),str(child.value))
dot.edge(str(self),str(child))
child.show(dot)
dot.render(directory='doctest-output').replace('\\', '/')

Related

How to traverse a tree with only one line? (python, tree traversal)

For a binary tree, we can traverse it in one line just like this (inorder, preorder, postorder is all ok):
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
# this is a preorder traversal with one line:
class Solution:
def preorderTraversal(self, root) -> List[int]:
return [] if root is None else [r.val] + self.preorderTraversal(r.left) + self.preorderTraversal(r.right)
For a tree that has multi-child in its node, how to complete the traversal work in one line?
I think list comprehension is a possible method, but I cannot complete the work in one line.
"""
# Definition for a Node.
class Node:
def __init__(self, val=None, children=None):
self.val = val
self.children = children
"""
class Solution:
def preorder(self, root: 'Node') -> List[int]:
if root is None: return []
ans = [root.val]
[ans.extend(x) for x in [self.preorder(child) for child in root.children]]
return ans
# This is a normal traversal:
# class Solution:
# def preorder(self, root: 'Node') -> List[int]:
# if root is None: return []
# ans = [root.val]
# for child in root.children:
# ans += self.preorder(child)
# return ans
Use a list comprehension to gather the traversal of all the root's children, regardless of how many children there are.
class Solution:
def preorderTraversal(self, root) -> List[int]:
# Original hard-coded approach for binary trees
# return [] if root is None else [r.val] \
# + self.preorderTraversal(root.left) + self.preorderTraversal(root.right)
# Generalized approach for binary trees
# return [] if root is None else [r.val] \
# + [y for child in [root.left, root.right] for y in self.preorderTraversal(child)]
# Generalized approach for a tree with arbitrary children per node
return [] if root is None else ([root.val]
+ [y for child in root.children for y in self.preorderTraversal(child)])
It could work like this:
class Solution:
def preorder(self, root):
return [] if root is None else [root.val] + [value
for child in (root.children or [])
for value in self.preorder(child)]
The idea is that list comprehension replaces a repeated call to append, not to extend. The non-comprehension code, that maps to the above list comprehension version, is:
class Solution:
def preorder(self, root):
if root is None:
return []
res = [root.val]
for child in (root.children or []):
for value in self.preorder(child):
res.append(value)
return res

How the yield statement of __iter__ works in TreeNode object (BST)

I'm implementing a simple binary sort tree in python; the code below is a snippet.
I've read about the __iter__ implemention of TreeNode somewhere, and I try to understand how it works. The code works fine, but I was wondering about one thing:
How does the yield statements actually works here? It seems it starts with the root, traversing the left tree first, print each element but still starts from the root every time.
class BinaryST(object):
def __init__(self):
self.root = None
self.size = 0
def __len__(self):
return self.size
def __iter__(self):
class EmptyIter():
def next(self):
raise StopIteration
if self.root:
return self.root.__iter__()
return EmptyIter()
class TreeNode(object):
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
def __iter__(self):
# visit the left tree
if self.has_left_child():
for child in self.left:
print 'yielding left child'
yield child
# back to current element; root
print 'yielding root ele'
yield self.val
if self.has_right_child():
for child in self.right:
print 'yield right child'
yield child
Output:
bt = bst.BST()
bt.insert(5)
bt.insert(7)
bt.insert(3)
bt.insert(1)
for i in bt:
print i
yielding root ele
yielding left child
yielding left child
1
yielding root ele
yielding left child
3
yielding root ele
5
yielding root ele
yield right child
7
I'm trying to understand the code flow here. How does the stack looks? Any help would be appreciated.

Counting nodes in General tree in python

I have created a Tree structure that is not a binary tree and having difficulties in getting the correct node count.
class TreeNode(object):
def __init__(self, name='root', children=None,Parent=[]):
self.Name = name
self.Parents=Parent
self.Children = []
if children is not None:
for child in children:
self.add_child(child.Name)
def __repr__(self):
return self.Name
def add_child(self, node):
self.Children.append(node)
and this is the latest in what I have tried to do in order to count the number of nodes in the tree.
def countNodes(Tree):
for Child in Tree.Children:
return countNodes(Child)+1
return 1
Could someone explain why this doesn't work?
EDIT: I should clarify, When I say doesn't work it gives me a completely wrong count for he number of nodes in my graph.
You countNodes function is not well. A parent node can have two childs, if you put a return statement within the for loop, it will return on the first child count and the second child count will be missing. You need to do something like this:
def countNodes(Tree):
count = 1
for Child in Tree.Children:
count += countNodes(Child)
return count
Just to add #levi has missed an edge case where root is None
so the modified code will be :
def numNodes(root):
if root == None:
return 0
node = 1
for child in root.children:
node = node + numNodes(child)
return node

How to add a grandchild to a python tree?

I'm trying to implement a Tree in python, I found this thread and tried to work my own tree, but I got stuck at how to add grand childrens.
the tree I'm trying to construct is like:
Root
ch1
ch2
ch3
ch4
So I figured that the add_child() method should be recursive:
1, If the tree has no children, add children to Root
2, for each children of Root, if one of the children equals parent, add children to it and stop the loop(so the new child is actually a grand child).
3, if there is no match, call add_child() on the current children.
But my code gives me:
Root
ch1
ch2
ch3
ch4
Btw, every time I work with recursive algorithms I get confused, could anyone give me some good advice of how to write recursive codes? or is there any good tutorials?
class Node(object):
def __init__(self, data, parent=None):
self.data = data
self.children = []
self.parent = parent
def __repr__(self, level=0):
ret = "\t" * level + repr(self.data) + "\n"
for child in self.children:
ret += child.__repr__(level + 1)
return ret
def add_child(self, node, parent):
if self.children == []:
self.children.append(node)
return
for child in self.children:
if child == parent:
child.children.append(node)
return
else:
child.add_child(node, parent)
# self.children.append(node)
if __name__ == '__main__':
tree = Node('Root')
tree.add_child(Node('ch1'), 'Root')
tree.add_child(Node('ch2'), 'ch1')
tree.add_child(Node('ch3'), 'ch2')
tree.add_child(Node('ch4'), 'ch2')
print tree
The following section makes no sense:
if self.children == []:
self.children.append(node)
return
If a node has no children you automatically add the node to that node? What if the node should be added to a different parent?
You probably meant to write:
def add_child(self, node, parent):
if self.data == parent:
self.children.append(node)
return
for child in self.children:
child.add_child(node, parent)
which produces the tree as expected.

Inserting a value into a Binary Search Tree in Python

I am reviewing for my final and one of the practice problem asks to implement a function that puts a value into a binary search tree in Python. Here is the Tree implementation I am using.
class Tree(object):
def __init__(self, entry, left=None, right=None):
self.entry = entry
self.left = left
self.right = right
Here is the function I need to fill in.
def insert(item, tree):
"""
>>> t = Tree(5, Tree(1, None, Tree(4)), Tree(7, Tree(6), Tree(8)))
>>> insert(2, t)
>>> t
Tree(5, Tree(1, None, Tree(4, Tree(2), None)), Tree(7, Tree(6), Tree(8)))
"""
Can anyone help me implement this code, as I have no idea where to start? Thanks!
def insert(item, tree):
if (item < tree.entry):
if (tree.left != None):
insert(item, tree.left)
else:
tree.left = Tree(item)
else:
if (tree.right != None):
insert(item, tree.right)
else:
tree.right = Tree(item)
Tree is a Non linear data structure.A tree is created by set of vertices and set of edges.Average searching complexity is logn . Let's consider how to insert values to tree.
First of all , you would create a Vertices.In another way, you would create nodes.then , Those nodes which is created insert hierarchical manner.In creating Node class , You can initialize all the properties of Node class in constructor function.Actually like this,
class Node:
def __init__(self,data):
self.data=data
self.left=None
self.right=None
At beginning, Node's data=data, left child of Node is None and right child of Node is None.And then , you can create a binary search tree using those created nodes.
class tree:
def __init__(self):
self.root=None
def insert(self,data):
if(self.root==None):
self.root=Node(data)
else:
self._insert(data,self.root)
def _insert(self, data, curNode):
if(curNode.data>data):
if(curNode.left==None):
curNode.left=Node(data)
else:
self._insert(data,curNode.left)
else:
if(curNode.right==None):
curNode.right=Node(data)
else:
self._insert(data,curNode.right)
At first, root node is initialized under constructor method of tree class.And then insert nodes using insert function.Using any tree traversal method can be printed elements of tree..I think , you could understand.thank you!

Categories