Binary Search Tree - storing reference to parent node - python

I hope someone can help me, I'm not a programming professional, but am using Python to learn and experiment with binary trees.
Below is the code I have, and have attempted to try and store a reference to a node's parent in it's node, the storing of it's parent node, won't work for leaf nodes though. Is there a way of doing this during the process of building the tree?
I'd also like to know for a given node, whether is's a 'Left or 'Right' node. I thought seeing as the node is stored in an instance of TreeNode.left or TreeNode.right, I might be able to get a reference to this in Python, as in n._name_ or something like that. Could you tell me the correct way to find whether a node is left or right?
My ultimate goal will be to visualise my tree through a level order traversal.
class TreeNode:
left, right, data = None, None, 0
def __init__(self,nodeData, left = None, right = None, parent = None):
self.nodeData = nodeData
self.left = left
self.right = right
self.parent = self
class Tree:
def __init__(self):
self.root = None
def addNode(self, inputData):
return TreeNode(inputData)
def insertNode(self, parent, root, inputData):
if root == None:
return self.addNode(inputData)
else:
root.parent = parent
if inputData <= root.nodeData:
root.left = self.insertNode(root, root.left, inputData)
else:
root.right = self.insertNode(root, root.right, inputData)
return root

There are many, many things wrong with this. Since it's homework, I'll supply one hint.
def __init__(self,nodeData, left = None, right = None, parent = None):
self.nodeData = nodeData
self.left = left
self.right = right
self.parent = self
Why isn't self.parent set to parent?

Related

Binary tree changing root

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.

Classes Binary Search Tree Python

I am new to Python and came across an old problem in HackerRank which defines a Binary Tree as such. I reviewed this video on classes and instances (and the next one) to try to understand what is happening in the below code but I still don't fully grasp what is going on.
I understand the role of the __ init __(self, ...) but I'm not sure what attribute info has. I also do not understand why self.left = None, self.right = None, self.level = None.
In the second class BinarySearchTree, there's an init with no attribute and I also do not understand the self.root = None.
Even though I don't understand most of the code below, I think if someone can explain why the person set self.____= None, it would help me understand how to define a Binary Search Tree.
class Node:
def __init__(self, info):
self.info = info
self.left = None
self.right = None
self.level = None
def __str__(self):
return str(self.info)
class BinarySearchTree:
def __init__(self):
self.root = None
def create(self, val):
if self.root == None:
self.root = Node(val)
else:
current = self.root
while True:
if val < current.info:
if current.left:
current = current.left
else:
current.left = Node(val)
break
elif val > current.info:
if current.right:
current = current.right
else:
current.right = Node(val)
break
else:
break
If you try sketch your tree structure as a bunch of circles with some values inside, you will get something like that:
The 'info' attribute will contain the values that are inside of the circles. Every node of a binary tree can have at most two children, that's what the 'left' and 'right' attributes are used for. If the 'left' attribute is 'None', it basically means there is no child node on the left side yet (like in case of the node 16 on the image). If you create a new node, you usually do not expect it to have any children, that's why the 'left' and 'right' attributes are 'None' by default.
The class 'BinarySearchTree' represents a tree as a whole and keeps the current root node (the top one on the image) in the corresponding 'root' attribute. At the beginning the tree is empty, so the 'root' attribute equals to 'None'.
Hope it helps!

Recursive function failing while inorder traverse in tree ds

I am trying to implement tree data structure but I am stuck and having trouble understanding how to create a recursive function for inorder traversal for my binary tree.
This is what i have done so far:
class Node:
def __init__(self, node):
self.node = node
self.left = None
self.right= None
def inorder_traversal(self):
if self.node != None:
return inorder_traversal(self.node.left)
return self.node
return inorder_traversal(self.node.right)
I don't seem to understand what's wrong.
Test inputs:
root = Node(1)
root.left = Node(3)
root.right = Node(4)
Error:
File "trees-implementation.py", line 23, in inorder_traversal
return inorder_traversal(self.node.left)
NameError: name 'inorder_traversal' is not defined
It looks like you've defined your traversal functions with respect to the Node. Does this make sense to you?
You should define a traversal with respect to the Tree, not the Node. The Node does not know it belongs to the tree, it's a dumb object.
Define the node.
class Node:
def __init__(self, value):
self.value = value
self.left = None
self.right= None
Define the tree. Also define your traversal methods here.
class Tree:
def __init__(self, root=None):
self.root = root
def inorder_traversal(self):
def _inorder(root):
if root != None:
yield from _inorder(root.left)
yield root.value
yield from _inorder(root.right)
return list(_inorder(self.root))
Initialise the tree with a root, and then traverse it.
tree = Tree(root)
tree.inorder_traversal()
[3, 1, 4]
First, could you check if when you have your object, you don't put a parameter in
root = Node()
Then are you sure you can have several returns in your inorder_traversal() function ?
Finally, the function is in the class Node() so if you call it try to add self.yourfunction

Python: actually modify a node in binary search tree instead of just attaching a label name

I understand how to insert using recursion. I also understand why this code doesn't work as expected because while I'm updating the variable "current" in the "insert" method, I'm only attaching the name label "current" to some node, copy that node to "current" and modify "current", but not the actual node in the binary search tree.
So how can I actually modify the node in the binary search tree using the iterative concept here? And more generally speaking, how can I make a "shallow copy" to any object I created and actually modify that object? A "list" object in Python is an example that has the desired property. What code in "list" makes it behave this way? Thanks in advance.
class Node:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
class BinarySearchTree:
def __init__(self, root=None):
self.root = root
def insert(self, data):
if self.root:
current = self.root
while current:
if data < current.data:
current = current.left
elif data > current.data:
current = current.right
current = Node(data)
else:
self.root = Node(data)
bst = BinarySearchTree()
bst.insert(2)
bst.insert(1)
bst.insert(3)

Delete a root from a tree in python

I am implementing a deletion of a node from a binary search tree in python.
I got stuck in an edge case.
Consider next code:
class Node():
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
root = Node(5)
root.right = Node(10)
How to implement a function that deletes the root.
I do not want the function return new root.
In C++ I can modify pointer to make root point to its child, however in python variables are labels essentially. Is it even possible to do in python?
There is indeed no way to replace root and have it replaced wherever the instance pointed to by the name root appears.
The only way to achieve what you want is to mutate root to duplicate the child node.
def delete(node, inheritLeft=True):
child = node.left if inheritLeft else node.right
node.value = child.value
node.left = child.left
node.right = child.right
(Obviously you might want to do something smarter regarding choosing which node to inherit).

Categories

Resources