def Search(root,key):
if root is None:
return 0
if(root.val == key):
return 1
if(root.val < key):
Search(root.right,key)
elif(root.val > key):
Search(root.left,key)
Above is a Python code that is supposed to return 1 if the given node exists in the Red-Black Tree and 0 if it doesn't. So the goal is, in the main() function, I will write
x = int(input())
print("Found") if Search(root,x)==1 else print("not found")
where x is the node to be checked.
Unfortunately, Search(root,x) is of return type "None" and I don't know how to fix this.
You just forgot the return keyword for the two recursive calls.
def Search(root,key):
if root is None:
return 0
if(root.val == key):
return 1
if(root.val < key):
return Search(root.right,key)
elif(root.val > key):
return Search(root.left,key)
Related
I have two classes, Node() and binarySearchTree().
Node() has the attributes:
self.left= None
self.right= None
self.key= key
self.data = data
And binarySearchTree() has methods for inserting, searching and printing the binary search tree (BST). I must also include a __contains__ method for my BST, which enables me to write something like:
tree= Bintree()
tree.store("table")
if "table" in tree: <--
do something <--
It complains about the last two "__contains__" that they're not defined. But I'd like it to work recursively. But it's not working.
def __contains__(self, key):
if self.root == None:
return False
elif key== self.root.key:
return True
elif key < self.root.key:
return __contains__(self.root.key.left,key)
elif key > self.root.key:
return __contains__(self.root.key.right,key)
__contains__ is not a global variable; it's a class attribute, and so must be accessed via BinTree or one of its instances. At the very least, you need to write
def __contains__(self, key):
if self.root == None:
return False
elif key == self.root.key:
return True
elif key < self.root.key:
return BinTree.__contains__(self.root.left, key)
elif key > self.root.key:
return BinTree.__contains__(self.root.right, key)
(Note that the key attribute isn't needed in the first argument; it's self.root itself, not its key, that has left and right attributes.
However, this is just a non-standard way of calling an instance attribute that prevents inherited from working correctly. It will also fail if you change the name of the class without updating the definition of the method to use the new name. The next best thing would be to invoke the method normally.
def __contains__(self, key):
if self.root == None:
return False
elif key == self.root.key:
return True
elif key < self.root.key:
return self.root.left.__contains__(key)
elif key > self.root.key:
return self.root.right.__contains__(key)
But best of all is to not call __contains__ directly, but use to use in, which will invoke __contains__ for you.
def __contains__(self, key):
if self.root == None:
return False
elif key == self.root.key:
return True
elif key < self.root.key:
return key in self.root.left
else: # key > self.root.key is the only option left
return key in self.root.right
WARNING: All of the above assumes that self.root.left and self.root.right exist and are not None, an assumption that may not be accurate but cannot be confirmed without code showing how a BinTree is constructed.
If you have separate tree and node types, you want two functions, one of them recursing through the nodes and the other just to get things going.
Something like this:
def __contains__(self, key):
returns self.node_contains(self.root, key)
def node_contains(self, node, key):
if node == None:
return False
elif key == node.key:
return True
elif key < node.key:
return self.node_contains(node.left, key)
elif key > node.key:
return self.node_contains(node.right, key)
or, you could divide the work between the classes, which could look like
In the tree class:
def __contains__(self, key):
return self.root and key in self.root
In the node class:
def __contains__(self, key):
return self.key == key
or (key < self.key and self.left and key in self.left)
or (self.right and key in self.right)
Trivial fix
1 def __contains__(self, key):
2 if self.root == None:
3 return False
4 elif key== self.root.key:
5 return True
6 elif key < self.root.key:
7 return self.__contains__(self.root.key.left,key)
8 elif key > self.root.key:
9 return self.__contains__(self.root.key.right,key)
just call self.__contains__
I am inexperienced in python.
I'm doing a college activity and I wrote a class to find the height of a binary tree.
But when I'm going to call the function recursively I have the message:
NameError Traceback (most recent call last)
<ipython-input-5-109fbd93416e> in <module>
7 raiz.insert(3)
8
----> 9 heigth(raiz)
NameError: name 'heigth' is not defined
The function is :
def heigth(self, n:"Node")-> int:
if n:
return 1
else:
left = heigth(n.left)
right = heigth(n.right)
if(left < right):
return right + 1
else:
return left + 1
All code:
from typing import List
class Node:
def __init__(self, key, left:"Node"=None, right:"Node"=None):
self.key = key
self.left = left
self.right = right
def print_tree(self):
"""
Prints the tree from the current node
"""
if self.left:
self.left.print_tree()
print(self.key, end=" ")
if self.right:
self.right.print_tree()
def insert(self, key) -> bool:
"""
Insert a node in the tree that has the key "key"
"""
if key < self.key:
if self.left:
return self.left.insert(key)
else:
self.left = Node(key)
return True
elif key > self.key:
if self.right:
return self.right.insert(key)
else:
self.right = Node(key)
return True
else:
return False
def search(self, key) -> bool:
"""
Returns true if the key exists in the tree
"""
if key < self.key:
if self.left:
return self.left.search(key)
elif key > self.key:
if self.right:
return self.right.search(key)
else:
return True
return False
def to_sorted_array(self, arr_result:List =None) -> List:
"""
Returns a vector of the ordered keys.
arr_result: Parameter with the items already added.
"""
if(arr_result == None):
arr_result = []
if self.left:
self.left.to_sorted_array(arr_result)
arr_result.append(self.key)
if self.right:
self.right.to_sorted_array(arr_result)
return arr_result
def max_depth(self,current_max_depth:int=0) -> int:
"""
calculates the greatest distance between the root node and the leaf
current_max_depth: Value representing the longest distance so far
when calling for the first time, there is no need to use it
"""
current_max_depth = current_max_depth +1
val_left,val_right = current_max_depth,current_max_depth
if self.left:
val_left = self.left.max_depth(current_max_depth)
if self.right:
val_right = self.right.max_depth(current_max_depth)
if(val_left>val_right):
return val_left
else:
return val_right
def position_node(self, key, current_position:int=1) -> int:
"""
Returns the position of the desired node in the tree
current_position: represents the position of the tree at that moment
when calling for the first time, there is no need to use it
"""
if key < self.key:
if self.left:
return self.left.position_node(key, current_position*2)
elif key > self.key:
if self.right:
return self.right.position_node(key, current_position*2+1)
else:
return current_position
def heigth(self, n:"Node")-> int:
if n:
return 1
else:
left = heigth(n.left)
right = heigth(n.right)
if(left < right):
return right + 1
else:
return left + 1
You are using method of a class, but when you refer to it just as a heigth it looks for the method not in a class of the object, but on a module level where it can't find it, hence the error.
Try replacing heigth calls with self.heigth, so that method of a class is called.
You cannot call the function in classes you must call the class first using self than the function:
left = self.height(n.left)
right = self.height(n.right)
You can make height a static method of Node.
You have to call the height method with the raiz instance as argument.
class Node:
# ...
#staticmethod
def height(n:"Node")-> int:
return 1 + max(self.height(n.left), self.height(n.right)) if n else 0
raiz.insert(3)
print(Node.height(raiz))
Or make it a recursive method
class Node:
# ...
def _height(self, n:"Node") -> int:
return n.height() if n else 0
def height(self) -> int:
return 1 + max(self._height(self.left), self._height(self.right))
raiz.insert(3)
print(raiz.height())
I was just wondering would anyone be able to help me. I am trying to do an inorder transversal of an AVL tree. But I keep getting an error that my function name 'r_in_order' is not defined. What is happening here and what am I missing? Here is the code:
class Node:
""" A node in a BST. It may have left and right subtrees """
def __init__(self, item, left = None, right = None):
self.item = item
self.left = left
self.right = right
class BST:
""" An implementation of a Binary Search Tree """
def __init__(self):
self.root = None
def recurse_add(self, ptr, item):
if ptr == None:
return Node(item)
elif item < ptr.item:
ptr.left = self.recurse_add(ptr.left, item)
elif item > ptr.item:
ptr.right = self.recurse_add(ptr.right, item)
return ptr
def add(self, item):
""" Add this item to its correct position on the tree """
self.root = self.recurse_add(self.root, item)
def r_count(self, ptr):
if ptr == None:
return 0
else:
return 1 + self.r_count(ptr.left) + self.r_count(ptr.right)
def count(self):
return self.r_count(self.root)
def r_height(self, ptr):
if ptr == None:
return 0
else:
return 1 + max(self.r_height(ptr.left), self.r_height(ptr.right))
def height(self):
return self.r_height(self.root)
def r_in_order(self, ptr):
if ptr != None:
r_in_order(ptr.left)
print(ptr.item + " ", end="")
r_in_order(ptr.right)
def in_order(self):
return self.r_in_order(self.root)
I am then testing the code with this:
import sys
from BST import BST
def main():
# Read each test case
line = sys.stdin.readline()
items = line.strip().split()
nums = [int(item) for item in items]
tree = BST()
for num in nums:
tree.add(num)
print("Print the elements of the tree in order:")
tree.in_order()
if __name__ == "__main__":
main()
r_in_order is a method of BST. It can only be called on a BST instance (or on the class with an instance as the first argument), but in the definition of r_in_order itself, you try to use it without one. So technically, it doesn't exist in the namespace you're trying to use it in.
Your function definition should be as follows:
def r_in_order(self, ptr):
if ptr != None:
self.r_in_order(ptr.left)
print(ptr.item + " ", end="")
self.r_in_order(ptr.right)
There is no general function r_in_order: you need to add self. to get a reference to the method you're already inside. There's also a syntax error lurking in the print statement. Try this:
def r_in_order(self, ptr):
if ptr != None:
self.r_in_order(ptr.left)
print(ptr.item, " ", end="")
self.r_in_order(ptr.right)
This runs, and yields the below (first line is input).
1 3 7 5 6 4 2
Print the elements of the tree in order:
1 2 3 4 5 6 7
I'm practicing creating a balanced binary search tree in python.
I already have these below, any idea on how to create a balance_bst funtion that passed a list of unique values that are
sorted in increasing order. It returns a reference to the root of a well-balanced binary search tree:
class LN:
def __init__(self,value,next=None):
self.value = value
self.next = next
def list_to_ll(l):
if l == []:
return None
front = rear = LN(l[0])
for v in l[1:]:
rear.next = LN(v)
rear = rear.next
return front
def str_ll(ll):
answer = ''
while ll != None:
answer += str(ll.value)+'->'
ll = ll.next
return answer + 'None'
# Tree Node class and helper functions (to set up problem)
class TN:
def __init__(self,value,left=None,right=None):
self.value = value
self.left = left
self.right = right
def height(atree):
if atree == None:
return -1
else:
return 1+ max(height(atree.left),height(atree.right))
def size(t):
if t == None:
return 0
else:
return 1 + size(t.left) + size(t.right)
def is_balanced(t):
if t == None:
return True
else:
return abs(size(t.left)-size(t.right)) <= 1 and is_balanced(t.left) and is_balanced(t.right)
def str_tree(atree,indent_char ='.',indent_delta=2):
def str_tree_1(indent,atree):
if atree == None:
return ''
else:
answer = ''
answer += str_tree_1(indent+indent_delta,atree.right)
answer += indent*indent_char+str(atree.value)+'\n'
answer += str_tree_1(indent+indent_delta,atree.left)
return answer
return str_tree_1(0,atree)
How do write the balance_bst?
def balance_bst(l):
Here is what I did:
def build_balanced_bst(l):
if l == None:
return None
else:
middle = len(l) // 2
return TN(l[middle],
build_balanced_bst(l[:middle]),
build_balanced_bst(l[middle + 1:]))
It gives me:
IndexError: list index out of range
How do I fix it?
I'm not going to write it for you since that's not what SO is about, but here's the general idea. Since the list is already sorted, the root should be the element in the middle of the list. Its left child will be the root of the balanced tree consisting of the elements to the left of the root in the list, and the right sub-tree will be the rest.
class MyHashTable:
def __init__(self, capacity):
self.capacity = capacity
self.slots = [None] * self.capacity
def __str__(self):
return str(self.slots )
def __len__(self):
count = 0
for i in self.slots:
if i != None:
count += 1
return count
def hash_function(self, key):
slot = key % len(self.slots)
if key in self.slots:
return slot
elif (not key in self.slots) and len(self.slots) == self.capacity:
return slot
else:
for i in self.slots:
count = 0
if i == None:
return count
count += 1
def insert(self, key):
print(len(self.slots)) #Why does this show an output of 2?
if key in self.slots:
return -2
elif (not key in self.slots) and (len(self.slots) != self.capacity): #Now this cant execute
num = hash_function(key)
self.slots[num] = key
return num
elif (not key in self.slots) and len(self.slots) == self.capacity:
return -1
Im wondering why the commented part above in the insert(self, key) the print statement gives (2) instead of (0). The elif statement underneath wont execute since its giving a result of (2) instead of (0)
A function call of
x = MyHashTable(2)
print(len(x))
Should give: 0
You're initializing self.slots = [None] * self.capacity, so with capacity = 2, self.slots is [None, None], which is of length 2.
Your __len__ method doesn't run because len(self.slot) calls self.slot.__len__, not self.__len__. If you'd like to use your override method, you should be calling len(self) instead.
You have to call your __len__ function (by calling self.__len__() ) if you want the length of the elements which are not None. For lists None are valid entries.
By the way. It is always best to compare with None by a is None or a is not None instead of == or !=.