I have a list of data indicates what direction is going next like:
[[0,1,0,0,1],[0,0,1],[0,0],[0,1,1,1,0]]
I want to implement this data into a tree structure like:
The number inside the node is how many people walked on this direction.
I have a Tree class that I write myself like this:
class Tree(object):
def __init__(self):
self.left = None
self.right = None
self.data = 0
def insert(self,num):
self.data = self.data + 1
if num == 0:
if self.left == None:
self.left = Tree()
return self.left
elif num == 1:
if self.right == None:
self.right = Tree()
return self.right
How can I do this? I tried to make it in a recursive way but turns out it's not saving under root but build_tree which is a variable that I tried to make as the recursive pointer.
root = Tree()
for route in data:
build_tree = root
for i in range (0,len(route)):
num = route[i]
build_tree = build_tree.insert(num)
Thanks!
Edit: This code actually works just like Blender said in comment. I think I had something wrong when I implemented it to a more complex code.
Also thanks John La Rooy for the suggestion and Kevin K. for the example!
Try making a separate class for the node like so
class Node:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
Then in your Tree class initialize self.root and declare your functions with recursion within Tree
Edit: Here is an example.
Related
I am trying to learn Python better, and I know one can easily find the solution for adding items into BTS, but I do not understand why my implementation of add method does not work? Can someone please help?
class Node:
def __init__(self, data, left = None, right = None):
self.data = data
self.left = left
self.right = right
class Tree:
def __init__(self):
self.root = None
def add(self, data):
self.root = self._add(data,self.root)
# if I change this line with just "self._add(data,self.root)" it would not iterate tree at all..
def _add(self,data,root):
if root is None:
root = Node(data)
return root
elif data <= root.data:
root.left = self._add(data, root.left)
else:
root.right = self._add(data,root.right)
def in_order(self):
if self.root is not None:
self._in_order(self.root)
def _in_order(self, root):
if root is not None:
self._in_order(root.left)
print(str(root.data) + ' ')
self._in_order(root.right)
I am printing in classical in-order fashion. My question is after inserting a few numbers, why do I still get the result for a root node to be None ?
This kind of implementation worked for me before in C or in Java, but in Python it does not work.
EDIT: I added my in-order method.
I have also tried this but it also does not work:
def add(self,data):
if self.root == None:
self.root = Node(data)
elif data <= self.root.data:
self.root.left = self.add(self.root.left,data)
else:
self.root.right = self.add(self.root.right,data)
I get a TypeError: add() takes 2 positional arguments but 3 were given
My question is after inserting a few numbers, why do I still get the result for a root node to be None ?
With this following line, you're setting self.root to be the return value of the method _add. Since this method has no return statement, it returns None by default.
self.root = self._add(data,self.root)
I get a TypeError: add() takes 2 positional arguments but 3 were given
In this case, you're calling self.add(self.root.left,data) with three parameters: the implicit self reference, self.root.left and data.
However, the method declaration receives only the parameters self and data.
I'm starting to study binary trees, and found this code in a teaching website
class Node:
def __init__(self, data):
self.left = None
self.right = None
self.data = data
def insert(self, data):
# Compare the new value with the parent node
if self.data:
if data < self.data:
if self.left is None:
self.left = Node(data)
else:
self.left.insert(data)
elif data > self.data:
if self.right is None:
self.right = Node(data)
else:
self.right.insert(data)
else:
self.data = data
# Print the tree
def PrintTree(self):
if self.left:
self.left.PrintTree()
print( self.data),
if self.right:
self.right.PrintTree()
# Use the insert method to add nodes
root = Node(27)
root.insert(14)
root.insert(35)
root.insert(31)
root.insert(10)
root.insert(19)
root.PrintTree()
And after debugging said code, i noticed that the correct root value was set at the beggining, but after a few steps changed to another value.
At the end, the root value was set with the correct int (the first value), but i can't understand why.
Also, is there a better way to create a binary tree and insert values in python?
I think you're being fooled by the debugger. After the first three statements, you'll have three objects: One named root, one named root.left, one named root.right:
root.data = 27
root.left.data = 14
root.right.data = 35
If you were then tracing through inserting 31, you'd get to the part in insert where it calls self.right.insert(data). At that point, you'll start insert again, but now self is the node in root.right. It's not root any more.
So, I am trying to define a function which would invert a binary tree, and when I run the below code, and then execute a_node.binInversion(), I get the error which says, "NameError: name 'binInversion' is not defined". Why is that error happening?
The code I'm executing is as below:
class BinaryTree:
def __init__(self, value):
self.value = value
self.left = None
self.right = None
def insert_left(self, value):
if self.left == None:
self.left = BinaryTree(value)
else:
new_node = BinaryTree(value)
new_node.left = self.left
self.left = new_node
def insert_right(self, value):
if self.right == None:
self.right = BinaryTree(value)
else:
new_node = BinaryTree(value)
new_node.right = self.right
self.right = new_node
def binInversion(self):
if self.left is None and self.right is None:
return 0
else:
binInversion(self.left)
binInversion(self.right)
self.left, self.right = self.right, self.left
a_node = BinaryTree('a')
a_node.insert_left('b')
a_node.insert_right('c')
b_node = a_node.left
b_node.insert_right('d')
c_node = a_node.right
c_node.insert_left('e')
c_node.insert_right('f')
d_node = b_node.right
e_node = c_node.left
f_node = c_node.right
a_node.binInversion()
Also, I know that there are high chances of binInversion() function not working as expected. Please DO NOT disclose the solution for inverting a binary tree, as I want to give it a shot on my own before looking at the solution.
a few bugs here:
binInversion is not a function, it is a class method, remember to call self.binInversion() instead of binInversion()
after the above fix, there will still be an error that says something along the lines of binInversion was given too many arguments. Your method of binInversion takes no arguments, try something like def binInversion(self, node) to pass in another argument or node.
Hi my question is how can i fix the code for my add function for my binary search tree program.
class BTNode2:
def __init__(self,d,l,r):
self.data = d
self.left = l
self.right = r
self.mult = 1
And this is the add method
def add(self, d):
if (self < d.data):
if (d.left != None):
add(self, d.left)
else:
d.left = BTNode2(self)
else:
if (d.right != None):
add(self, d.right)
else:
d.right = BTNode2(self)
return
This is the error i get when i try to run the add method:
AttributeError: 'str' object has no attribute 'data'
In essence, you swapped the parameters of the add function, since self is the tree here, and d the data element to add. Furthermore in order to construct such BTNode2s with only one parameter, you should add a default value for l and r. Finally depending on what mult does, you might want to change this in the add algorithm, but it is not really clear what it represents.
So we can fix this to:
class BTNode2:
def __init__(self, d, l=None, r=None):
self.data = d
self.left = l
self.right = r
self.mult = 1
def add(self, d):
if d < self.data:
if self.left is not None:
self.left.add(d)
else:
self.left = BTNode2(d)
else:
if self.right is not None:
self.right.add(d)
else:
self.right = BTNode2(d)
I have been struggling with this problem for a while and I am a Python beginner when it comes to BST, so I would appreciate some help. I am dynamically adding elements from an (unsorted) array into BST. That part is fine, I know how to do that. The next step, proved to be impossible with my current skill set. As I am adding elements to the tree, I need to be able to find current rank of any element in the tree. I know there are subtleties in this problem, so I would need help to at least find the number of nodes that are below the given node in BST. For example, in this case, node 15 has nodes 10,5 and 13 below it, so the function will return 3. Here is my existing code [this is a problem from Cracking the coding interview, chapter 11]
class Node:
"""docstring for Node"""
def __init__(self, data):
self.data = data
self.left=None
self.right=None
self.numLeftChildren=0
self.numRightChildren=0
class BSTree:
def __init__(self):
self.root = None
def addNode(self, data):
return Node(data)
def insert(self, root, data):
if root == None:
return self.addNode(data)
else:
if data <= root.data:
root.numLeftChildren+=1
root.left = self.insert(root.left, data)
else:
root.numRightChildren+=1
root.right = self.insert(root.right, data)
return root
def getRankOfNumber(self,root,x):
if root==None:
return 0
else:
if x>root.data :
return self.getRankOfNumber(root.right,x)+root.numLeftChildren+1
elif root.data==x:
return root.numLeftChildren
else:
return self.getRankOfNumber(root.left,x)
BTree=BSTree()
root=BTree.addNode(20)
BTree.insert(root,25)
BTree.insert(root,15)
BTree.insert(root,10)
BTree.insert(root,5)
BTree.insert(root,13)
BTree.insert(root,23)
You can go by this approach:
1. Have 2 more fields in each node numLeftChildren and numRightChildren.
2. Initialize both of them to 0 when you create a new node.
3. At the time of insertion, you make a comparison if the newly added node's
key is less than root's key than you increment, root's numLeftChildren and
call recursion on root's left child with the new node.
4. Do Same thing if new node's key is greater than root's key.
Now, come back to your original problem, You have to find out the number of children in left subtree. Just find out that node in O(logN) time and just print the numLeftChildren
Time Complexity: O(logN)
PS: I have added another field numRightChildren which you can remove if you are always interested in knowing the number of nodes in left subtree only.
You could modify your BST to contain the number of nodes beneath each node.
Or you could iterate over a traditional BST from least to greatest, counting as you go, and stop counting when you find a node of the required value.
You could simplify the code by using just instances of the Node class, as your BSTree instance operates on the root node anyway. Another optimization could be to not represent duplicate values as separate nodes, but instead use a counter of occurrences of the key:
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
self.num_left_children = 0
self.occurrences = 1
def insert(self, data):
if data < self.data:
if self.left is None:
self.left = Node(data)
else:
self.left.insert(data)
self.num_left_children += 1
elif data > self.data:
if self.right is None:
self.right = Node(data)
else:
self.right.insert(data)
else:
self.occurrences += 1
def get_rank(self, data):
if data < self.data:
return self.left.get_rank(data)
elif data > self.data:
return (self.occurrences + self.num_left_children +
self.right.get_rank(data))
else:
return self.num_left_children
Demo:
root = Node(20)
root.insert(25)
root.insert(15)
root.insert(10)
root.insert(10)
root.insert(5)
root.insert(13)
root.insert(23)
print(root.get_rank(15)) # 4
You can use the below function to find the number of the nodes in the tree (including the root).
def countNodes(self, root):
if root == None:
return 0
else
return (1 + countNodes(root.left) + countNodes(root.right));
To find the number of nodes that lie below root, subtract 1 from the value returned by the function. I think this will help get you started on the problem.
Your code will look like:
class Node:
"""docstring for Node"""
def init(self, data):
self.data = data
self.left=None
self.right=None
self.depth=0
class BSTree:
def init(self):
self.root = None
def addNode(self, data):
return Node(data)
def insert(self, root, data):
if root == None:
return self.addNode(data)
else:
if data <= root.data:
root.left = self.insert(root.left, data)
else:
root.right = self.insert(root.right, data)
return root
BTree=BSTree()
root=BTree.addNode(20)
BTree.insert(root,25)
BTree.insert(root,15)
BTree.insert(root,10)
BTree.insert(root,5)
BTree.insert(root,13)
BTree.insert(root,23)
BTree.insert(root,23)
numLeft = countNodes(root->left);
numRight = countNodes(root->right);
numChildren = numLeft + numRight;