Counting nodes in General tree in python - 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

Related

Binary Tree Conditional Insert

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)

How to count all the nodes after parent node in python

In the given tree when we pass node-- 2 then output is 5, it counts all the nodes after 2,
4-5-6-7-8
def count(node):
if node is None:
return 0
return 1+count(node.lchild)+count(node.rchild)
but with this, I only count its child nodes
As others have said, your code is designed for node instances that have lchild and rchild members, but the tree in the picture has a node with 3 children, so it cannot be represented as such a node.
You need a different definition of your Node class:
class Node:
def __init__(self, value, *children):
self.value = value
self.children = children
Then I would define count as a method of that class, not as a stand-alone function:
class Node
# ...
def count(self):
return sum(1 + child.count() for child in self.children)
Example run:
# Create the tree as pictured in the question
root = Node(1,
Node(2,
Node(4),
Node(5,
Node(7),
Node(8)
),
Node(6)),
Node(3)
)
# Select the node with value 2 (at left of root) and call the `count` method:
print(root.children[0].count())
Your code runs correctly on Binary Tree but the Tree of your question is not Binary Tree, you need a different approach. You need to define list of child for every node in your class and use this code:
def count(node):
if node is None:
return 0
count = 1
for child in node_child
count += count(child)
return count

Recursive insert into a tree with 4 children

I'm trying to construct a tree in Python that can take 4 children. The children are defined as an array.
What I'm struggling with is inserting recursively into this tree.
Here is what I've done so far:
Node Class:
class node:
def __init__(self,value,city,children=[None,None,None,None]):
self.value = value
self.children = children
self.city = city
Tree Class:
from node import *
from isFull import *
class tree:
root = None
def __int__(self):
self.root = None
def insert(self, city, value):
if self.root == None:
self.root = node(value, city, children=[None,None,None,None])
else:
self.rec_insert(city, value, self.root, 0)
def rec_insert(self, city, value, nodes, index):
if nodes.children[index] is None:
nodes.children[index] = node(value, city, children=[None,None,None,None])
return
elif index < 3:
self.rec_insert(city, value, nodes, index + 1)
elif index == 3:
self.rec_insert(city, value, nodes.children[0], 0)
So what I have observed is that this first if statement actually works. I can insert a root and into the first layer of children.
if nodes.children[index] is None:
Now the problem arises in level 2. Probably because I'm descending wrong.
At the start I can insert normally into layer 2, however as it gets to the right side of the tree it skips the last child in layer 2.
My logic behind this function:
self.rec_insert(city, value, nodes.children[0], 0)
I wanted to make it descend just into the left most child then my other conditional statements will make it shift right as it inserts.
This check:
elif index == 3:
I use it to determine if all the children have been inserted into in a node.
Any help will be appreciated.

Implementing Binary Search Tree (Python)

I have the task to perform some basic operations on Binary Search Trees and I'm not sure what is the clever way to do it.
I know that the usual way would be to write a class for the nodes and one for the tree so that I can build up my tree from given values and perform certain tasks on it. The thing is, I'm already getting the tree as a list and since BSTs are not unique, there won't come any good from it if I take each value and build the tree myself.
So... I'm getting a list like this:
11 9 2 13 _, 4 18 2 14 _, 2 10 _ 11 4, 14 16 4 _ _, 13 0 11 _ _ | 10 | 7
which means:
key value parent left right, ... | value1 | value2
So as you see the BST is given explicitly. My tasks are to do a level-print of the tree, return the path from root to value1, do a rotate-right operation on the subtree that has value1, then delete value1 and then insert value2.
What would be an efficient way to tackle this problem?
Here is one possible way of implementing the tree. Hope it helps. Though this contains insertions and popular traversals, not rotations or deletions.
Reference: http://www.thelearningpoint.net/computer-science/learning-python-programming-and-data-structures/learning-python-programming-and-data-structures--tutorial-20--graphs-breadth-and-depth-first-search-bfsdfs-dijkstra-algorithm-topological-search
'''
Binary Search Tree is a binary tree(that is every node has two branches),
in which the values contained in the left subtree is always less than the
root of that subtree, and the values contained in the right subtree is
always greater than the value of the root of the right subtree.
For more information about binary search trees, refer to :
http://en.wikipedia.org/wiki/Binary_search_tree
'''
#Only for use in Python 2.6.0a2 and later
from __future__ import print_function
class Node:
# Constructor to initialize data
# If data is not given by user,its taken as None
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
# __str__ returns string equivalent of Object
def __str__(self):
return "Node[Data = %s]" % (self.data,)
class BinarySearchTree:
def __init__(self):
self.root = None
'''
While inserting values in a binary search tree, we first check
whether the value is greater than, lesser than or equal to the
root of the tree.
We initialize current node as the root.
If the value is greater than the current node value, then we know that
its right location will be in the right subtree. So we make the current
element as the right node.
If the value is lesser than the current node value, then we know that
its right location will be in the left subtree. So we make the current
element as the left node.
If the value is equal to the current node value, then we know that the
value is already contained in the tree and doesn't need to be reinserted.
So we break from the loop.
'''
def insert(self, val):
if (self.root == None):
self.root = Node(val)
else:
current = self.root
while 1:
if (current.data > val):
if (current.left == None):
current.left = Node(val)
break
else:
current = current.left
elif (current.data < val):
if (current.right == None):
current.right = Node(val)
break
else:
current = current.right
else:
break
'''
In preorder traversal, we first print the current element, then
move on to the left subtree and finally to the right subree.
'''
def preorder(self, node):
if (node == None):
return
else:
print(node.data, end=" ")
self.preorder(node.left)
self.preorder(node.right)
'''
In inorder traversal, we first move to the left subtree, then print
the current element and finally move to the right subtree.
'''
#Important : Inorder traversal returns the elements in sorted form.
def inorder(self, node):
if (node == None):
return
else:
self.inorder(node.left)
print(node.data, end=" ")
self.inorder(node.right)
'''
In postorder traversal, we first move to the left subtree, then to the
right subtree and finally print the current element.
'''
def postorder(self, node):
if (node == None):
return
else:
self.postorder(node.left)
self.postorder(node.right)
print(node.data, end=" ")
tree = BinarySearchTree()
tree.insert(1)
tree.insert(9)
tree.insert(4)
tree.insert(3)
tree.insert(5)
tree.insert(7)
tree.insert(10)
tree.insert(0)
print ("Preorder Printing")
tree.preorder(tree.root)
print("\n\nInorder Printing")
tree.inorder(tree.root)
print("\n\nPostOrder Printing")
tree.postorder(tree.root)
Here is the implementation of Binary Search Tree with it's basic operations like insert node, find node
class Node:
def __init__(self,data):
self.left = None
self.right = None
self.data = data
class BST:
def __init__(self):
self.root = None
def set_root(self,data):
self.root = Node(data)
def insert_node(self,data):
if self.root is None:
self.set_root(data)
else:
n = Node(data)
troot = self.root
while troot:
if data < troot.data:
if troot.left:
troot = troot.left
else:
troot.left = n
break
else:
if troot.right:
troot = troot.right
else:
troot.right = n
break
def search_node(self,data):
if self.root is None:
return "Not found"
else:
troot = self.root
while troot:
if data < troot.data:
if troot.left:
troot = troot.left
if troot.data == data:
return "Found"
else:
return "Not found"
elif data > troot.data:
if troot.right:
troot = troot.right
if troot.data == data:
return "Found"
else:
return "Not found"
else:
return "Found"
tree = BST()
tree.insert_node(10)
tree.insert_node(5)
tree.insert_node(20)
tree.insert_node(7)
print(tree.root.data)
print(tree.root.left.data)
print(tree.root.right.data)
print(tree.root.left.right.data)
print(tree.search_node(10))
print(tree.search_node(5))
print(tree.search_node(20))
print(tree.search_node(7))
print(tree.search_node(12))
print(tree.search_node(15))
Output:
10
5
20
7
Found
Found
Found
Found
Not found
Not found
In this specific case I had success using a dictionary as a datatype to store the graph. The key is the node_key and the value is a list with the attributes of the node. In this way it is rather fast to find the needed nodes and all its attributes.
I'm just not sure if there is a way to make it reasonably faster.

Adding Children Nodes to a Tree in Python

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.

Categories