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.
Related
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('\\', '/')
I am trying to write a logic to insert a node into a binary tree.
The node looks like this
class BinTree:
def __init__(self, Id):
self.Id = Id
self.NodeCounter = 1
self.left = None
self.right = None
I need to insert a new node only if it doesnt exist in the tree but increment the counter if it exists already.
As of now, what im doing is whenever i get a new element to insert, i first search it in the binary tree, if the node is found i increment the NodeCounter by 1, otherwise I again start traversing from root node and then go and insert the new node
The problem here is that for every new node, i am traversing the tree twice which i dont want… And when i am trying to search and insert at the same time,the counters get messed because of recursion.
Is there a way I can achieve this?
Any tips would be appreciated
i first search it in the binary tree
...this would only be an efficient process if your binary tree is a binary search tree (BST). I'll assume that is what we are talking about.
if the node is found i increment the NodeCounter by 1, otherwise I again start traversing from root node and then go and insert the new node
Why would you start from the root again? When you did the search and didn't find the node, there was a last node that you visited. Just attach the new node to it.
Here is a possible implementation:
class Node:
def __init__(self, id):
self.id = id
self.nodeCounter = 1
self.left = None
self.right = None
class BinTree:
def __init__(self):
self.root = None
def add(self, id):
self.root = self.addrecur(self.root, id)
def addrecur(self, node, id):
if not node:
node = Node(id)
elif id == node.id:
node.nodeCounter += 1
elif id < node.id:
node.left = self.addrecur(node.left, id)
else:
node.right = self.addrecur(node.right, id)
return node
def __repr__(self):
return self.indented(self.root)
def indented(self, node, indent=""):
if not node:
return ""
return (self.indented(node.right, indent + " ")
+ f"{indent}{node.id} ({node.nodeCounter})\n"
+ self.indented(node.left, indent + " "))
tree = BinTree()
tree.add(4)
tree.add(2)
tree.add(3)
tree.add(2)
tree.add(6)
tree.add(5)
tree.add(5)
print(tree)
This outputs the tree in side-ways view (root at left) with the node count in parentheses:
6 (1)
5 (2)
4 (1)
3 (1)
2 (2)
So I just started learning Python so forgive me if I'm missing something here. I have a simple node class that has data and children as a list. In another class where Im recursively going through a grid, I attempt to add the entire grid to a node to create a sort of state space for the problem. My issue is that when I'm adding a child to its parent, it also adds itself as a child to itself for some reason.
This is my node class
class StateSpaceNode:
def __init__(self, data=None, children=[]):
self.data = data
self.children = children
def add_data(self, data):
self.data = data
def add_child(self, child):
self.children.append(child)
and this is the portion where im adding the child
def traverse_dfs(self, grid, x, y, seen, root):
self.traverse_dfs_helper(grid, x, y, seen, root)
def traverse_dfs_helper(self, grid, x, y, seen, old_root):
key = "%s, %s" % (x, y)
seen[key] = True
if old_root.data is not None:
node = StateSpaceNode()
print("ADDING CHILD")
print("NEW NODE:", node)
print("NEW NODE CHILDREN: ", node.children)
node.add_data(copy.deepcopy(grid))
old_root.add_child(node)
print("PARENT CHILDREN:", old_root.children)
print("CHILDREN TO NEW NODE:", node.children)
else:
print("MAKING ROOT")
old_root.add_data(copy.deepcopy(grid))
print("OLD ROOT DATA ADDED", old_root.data)
node = old_root
print("CHILDREN TO OLD ROOT", node.children)
Take note of the print statements. This is the output for that portion of the code.
MAKING ROOT
OLD ROOT DATA ADDED [[0, 0], [0, 2]]
CHILDREN TO OLD ROOT []
ADDING CHILD
NEW NODE: <state_space.StateSpaceNode object at 0x104d2dcc0>
NEW NODE CHILDREN: []
PARENT CHILDREN: [<state_space.StateSpaceNode object at 0x104d2dcc0>]
CHILDREN TO NEW NODE: [<state_space.StateSpaceNode object at 0x104d2dcc0>]
and if I print the tree out, it just keeps going on and on with the same child. However, the "ADDING CHILD" portion only happens three times in total so Im not sure whats going on. Any help is appreciated!
I am trying to create a tree in python, which I want to be able to do a breadth first traversal later on. However, when I try to loop through the children of a node (i.e the root), it doesn't seem to find any children. However, if I try to access the child separately (root.children[1]) it is valid. I am pretty sure I am doing something silly, but I am not sure where. Here is my code:
class Component:
def __init__(self, compName, originName, connected = False): #removed to decrease code size
def __str__(self):
return "\n\tComponent Name: {0}\n\tOrigin Name: {1}\n\tConnected: {2}\n".format(self.name, self.origin, str(self.connected));
class Node:
def __init__(self, component, parent):
self.children = [];
def add_node(self, node):
self.children.append(node);
#...left out some broken code that is commented out...#
def __str__(self):
return "{0}".format(str(self.component));
class Tree:
def __init__(self):
def add_component(self, component, parent = None):
if self.root is None:
self.root = Node(component, parent);
else:
self.root.add_node(Node(component, parent));
def breadth_first(node):
result = [];
queue = [];
queue.append(node);
while queue:
node = queue.pop(0);
result.append(node);
plog("Adding to result\n");
plog(str(node));
if node in node.children:
for child in node.children:
if child not in result and child not in queue:
queue.append(child);
else:
plog("NO CHILDREN\n"); // this is being displayed
return result;
def main(ScriptArgument, oDesktop):
component = Component("Laminate", "B7_TX");
tree = Tree();
tree.add_component(component);
component = Component("B7", "B7_TX");
tree.add_component(component, "Laminate");
result = breadth_first(tree.root);
for x in result:
plog(str(x) + "\n");
This is the output I am getting:
Adding to result # output from breadth-first
Component Name: Laminate #output from breadth-first
Origin Name: B7_TX
Connected: False
NO CHILDREN # this is indicating that the child was not added properly, I believe
Component Name: Laminate # output from the loop in main
Origin Name: B7_TX
Connected: False
Why are you checking if the parent is in the list of children with the following line?
if node in node.children:
I would simply do:
[...]
while queue:
node = queue.pop(0);
result.append(node);
plog("Adding to result\n");
plog(str(node));
for child in node.children:
if child not in result and child not in queue:
queue.append(child);
return result;
My "if" check was wrong. I was checking to see if the root (or current) node is in its own children list, which was wrong. I simply changed this to check if there are any children (if node.children:) and it worked.
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