Recursion and return statements in python - python

I am trying to implement a 2-3 tree but I am having trouble with the find method.
This method given an int as parameter should return the node that contains the int.
The problem is that sometimes it works, sometimes it does't and I don't know why.
I have added a test print. For a particular int that I know for sure that is part of the tree, the code executes the print statement, meaning that it has found the node, but does not return this node. Instead it return False which is at the end of the code.
Can you help me solving this ?
def find(self,data,node=0): #return problem ???
if node==0:
a=self.root
else:
a=node
if a.data2==None:
if data==a.data: ### here is the problem
print("qwertyuiop") ### it does not execute the return statement
return a
elif data < a.data:
if a.left!=None:
return self.find(data,a.left)
elif data > a.data:
if a.right!=None:
return self.find(data,a.right)
else:
if a.data2!=None:
if (data==a.data or data==a.data2):
return a
elif data<a.data:
if a.left!=None:
return self.find(data,a.left)
elif (data>a.data and data<a.data2):
if a.middle!=None:
return self.find(data,a.middle)
elif data>a.data2:
if a.right!=None:
return self.find(data,a.right)
print("Not Found") ### function executes this print
return False
self.root is the root of the tree and is an object of the following class
class Node:
def __init__(self, data=None, left=None, right=None):
self.data = data
self.data2 = None
self.data3 = None
self.left = left
self.right = right
self.middle = None
self.middle2 = None
Binary Search Tree:
class Nodeee:
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
class BST:
def __init__(self, root=None):
self.c=[]
self.total=0
self.root = None
def parent(self,data,node=5):
def search(nodee,cc,data):
if data==cc.data:
return nodee
else:
if data<cc.data:
nodee=cc
return search(nodee,cc.left,data)
elif data>cc.data:
nodee=cc
return search(nodee,cc.right,data)
print("Parent Error")
return False
if node==self.root:
print("Root has no parent")
else:
a=self.root
c=self.root
return search(a,c,data)
def lookup(self,data,node=0):
if node==0:
a=self.root
else:
a=node
if data < a.data:
if a.left==None:
return a
else:
return self.lookup(data,a.left)
elif data > a.data:
if a.right==None:
return a
else:
return self.lookup(data,a.right)
def find(self,data,node=0):
if node==0:
a=self.root
else:
a=node
if data==a.data:
print("WTF")
return a
elif data < a.data:
if a.left!=None:
return self.find(data,a.left)
elif data > a.data:
if a.right!=None:
return self.find(data,a.right)
print("Not Found")
return False
def find2(self,data,node=0):
if node==0:
a=self.root
else:
a=node
if data==a.data:
return True
elif data < a.data:
return self.find2(data,a.left)
elif data > a.data:
return self.find2(data,a.right)
return False
def is_empty(self):
if self.root==None:
return True
def is_leaf(self,n):
if (n.left==None and n.right==None):
return True
return False
def delete(self):
self.root=None
def insert(self, data):
if self.root==None:
self.root=Nodeee(data)
self.total+=1
return True
else:
b=self.lookup(data)
if data < b.data:
b.left=Nodeee(data)
self.total+=1
return True
elif data > b.data:
b.right=Nodeee(data)
self.total+=1
return True
print("Insert Error !")
return False
def inorder_swap(self,data):
a=self.find(data)
b=a.right
while self.is_leaf(b)!=True:
if b.left!=None:
b=b.left
elif b.left==None:
b=b.right
temp=a.data
a.data=b.data
b.data=temp
def remove(self,data):
a=self.find(data)
if self.is_leaf(a)==True:
b=self.parent(data)
if b.left==a:
b.left=None
elif b.right==a:
b.right=None
elif self.is_leaf(a)==False:
if a.left==None:
b=self.parent(data)
if b.left==a:
b.left=b.left.right
elif b.right==a:
b.right=b.right.right
elif a.right==None:
b=self.parent(data)
if b.left==a:
b.left=b.left.left
elif b.right==a:
b.right=b.right.left
elif (a.left!=None and a.right!=None):
self.inorder_swap(data)
self.remove(data)
def inorder(self,node):
if node!=None:
self.inorder(node.left)
self.c.append(node.data)
self.inorder(node.right)
def inorder_print(self):
self.c=[]
self.inorder(self.root)
print("\nStart")
for x in range(len(self.c)):
print(self.c[x], end=",")
print("\nFinish\n")
a=BST()
print(a.insert(234)==True)
print(a.insert(13)==True)
print(a.insert(65)==True)
print(a.insert(658)==True)
print(a.insert(324)==True)
print(a.insert(86)==True)
print(a.insert(5)==True)
print(a.insert(76)==True)
print(a.insert(144)==True)
print(a.insert(546)==True)
print(a.insert(2344)==True)
print(a.insert(1213)==True)
print(a.insert(6345)==True)
print(a.insert(653348)==True)
print(a.insert(35324)==True)
print(a.insert(8463)==True)
print(a.insert(5555)==True)
print(a.insert(76539)==True)
print(a.insert(14499)==True)
print(a.insert(59999946)==True)
a.inorder_print()
a.remove(35324)
a.remove(1213)
a.remove(2344)
a.remove(144)
a.remove(5555)
a.remove(6345)
a.remove(59999946)
a.remove(76)
print(a.root.data)
a.inorder_print()

def inorder_swap(self,data):
a=self.find(data)
b=a.right
while self.is_leaf(b)!=True:
if b.left!=None:
b=b.left
elif b.left==None:
b=b.right
temp=a.data
a.data=b.data
b.data=temp
a here is the node containing the passed data. This method does nothing else than swapping a's data with some leaf's data (first one while finds), thereby distorting the tree order. A follow-up find on the same data therefore fails and returns False. Since your code has no error checks, this results in an AttributeError.
You probably want to move nodes around in inorder_swap. However you only assign to the local name b. If you want to change nodes, then you need to use b.left = or b.right =.
It might be that there are more problems, that I don't see right now.
Also your code has several style problems, some of them:
You have four functions doing the same: find, find2, lookup and search in parent.
Most of the naming is not informative or even confusing.
Lines like if a.right==None: should be written as if not a.right: (or maybe if a.right is None:).
Check the return value of functions and don't just assume they return a valid node if they might not (i.e. find might return False instead of a node). Or alternatively use exception handling.
If you have an if ... elif ... elif block you don't have to check the last possibility if it is sure to be true, for example:
if b.left!=None:
# something
elif b.left==None:
# something else
should be
if b.left:
# something
else:
# something else

Related

stack class in Python

I have written the below code to implement the stack class instead of using the build in function, not sure if I have got it rigth. Can someone please check for me and advise if there is an error?
class DSAStack():
maxCap = 100
def __init__(self):
self.stack = []
self.count = 0
def isEmpty(self):
if self.count == 0:
return True
else:
return false
def isFull(self):
if self.count == maxCap:
return True
else:
return false
def push(self, item):
if self.isFull:
raise ('Stack is full...')
else:
self.stack[self.count] = item
self.count += 1
def pop(self):
self.topVal = self.top
self.stack[self.count - 1] = 0
self.count = self.count - 1
return self.topVal
def top(self):
if self.isEmpty:
raise ('Stack is empty...')
else:
self.top = self.stack[self.count - 1]
Firstly, you need not keep track of count. Accessing the length of the list will do that for you.
def __init__(self):
self.stack =[]
Now, your logic for isEmpty and isFull was alright, but since we are removing the self.count variable, here's how you'd go about it
def isEmpty(self):
return len(self.stack) == 0 #Directly return true or false
def isFull(self):
return len(self.stack) == maxCap #Directly return true or false
In your push function, there are a few things I'd like to point out.
First, you need to call the isFull function. So we need to add parentheses to it.
Secondly, you cant just raise ('Stack is full...'), you will get a TypeError: Exceptions must derive from BaseException. This basically means what you raise must be some type of error.
Lastly, you can't add a new element by doing self.stack[self.count]=item since you will get an IndexError
Here are the changes:
def push(self,item):
if self.isFull(): #Need to call the function, self.isFull is not a variable
raise Exception('Stack is full...') #Or any other type of error
else:
self.stack.append(item) #Adds new item to the end of self.stack
Now coming to the pop function, setting a value to zero in a list does not really get rid of it. And it can cause a lot of confusion, especially since we are using the len(self.stack) to implement this.
Here's how you would pop:
def pop(self):
if self.isEmpty():
raise Exception('Stack is empty...')
else:
return self.stack.pop() #List has a built-in pop method
So now we don't really need the top function. And that concludes that. Btw, in your top function, you have defined self.top = self.stack[self.count-1]
Giving the same name to a function and a variable is never really a good idea.
To implement the pop functionality yourself, you could do the following:
def pop(self):
if self.isEmpty():
raise Exception('Stack is empty...')
else:
topVal = self.stack[-1] #-1 gives you the last element
#if stack will contain objects instead of primitive data types, use self.stack[-1].copy()
del self.stack[-1] #Deletes the element
return topVal
Polishing your top function will be like this:
def top(self):
if self.isEmpty():
raise Exception('Stack is empty...')
else:
return self.stack[-1]
def pop(self):
topVal = self.top()
del self.stack[-1]
return topVal
Note how the top function is defined before the pop function.
Also, try to test the code out and resolving any issues.

How to fix "global name --- is not defined error "

I created two classes, one for a node object and the other for a BST (binary search tree object). For the binary search tree, I have implemented two methods, one for inserting a given value (new_val) into the correct position in the tree and the other for searching the BST for a node with the given value. To implement these functions, I have created helper functions (i.e. insertRecursive and searchRecursive), which work recursively to attain the function goals. For some reason, when I run the code, I am getting the error "NameError: global name 'insert_Recursive' is not defined" and I am unsure why. Any advice on how to solve the issue would be much appreciated.
class Node(object):
def __init__(self, value):
self.value = value
self.left = None
self.right = None
class BST(object):
def __init__(self, root):
self.root = Node(root)
def insert(self, new_val):
self.insert_Recursive(self.root, new_val)
def insert_Recursive(self, start, new_val):
if start != None:
if (new_val > start.value):
insert_Recursive(start.right, new_val)
else:
insert_Recursive(start.left, new_val)
else:
start.value = new_val
def search(self, find_val):
return searchRecursive(self.root, find_val)
def searchRecursive(self, start, find_val):
if start != None:
if (find_val == start.value):
return True
elif(find_val > start.value):
searchRecursive(start.right, find_val)
else:
searchRecursive(start.left, find_val)
else:
return False
tree = BST(4)
tree.insert(2)
tree.insert(1)
tree.insert(3)
tree.insert(5)
print tree.search(4)
print tree.search(6)
if (new_val > start.value):
insert_Recursive(start.right, new_val)
Should be
if (new_val > start.value):
self.insert_Recursive(start.right, new_val)

not able to execute the delete function for binary seach tree in pytho.Please suggest the required edit

please suggest some edit in the delete function for the binary tree in python.I am not able to delete any element with this part of code.
def min_value_node(self,cur_node):
current=cur_node
while(current.left is not None):
current=current.left
return current
def delete(self,data):
if self.root==None:
return False
else:
return self._delete(data,self.root)
def _delete(self,data,cur_node):
if data>cur_node.data:
self. _delete(data,cur_node.right)
elif data>cur_node.data:
self. _delete(data,cur_node.right)
else:
if data==cur_node.data:
if cur_node.left is not None and cur_node.right is not None:
cur_node.data==self.min_value_node(cur_node.right)
else:
if cur_node.left == None:
cur_node = node.right
elif cur_node.right == None:
cur_node = node.left

Binary Search Tree (Python) not showing result

I'm somewhat new to Python and need help with an issue I'm facing. I'm trying to make a binary search tree. I've written a code and it works, but won't show any result (printed values). I can't figure out what the issue might be. Here is the entire code:
class Node:
def __init__(self, value):
self.value = value
self.left_child = None
self.right_child = None
class binary_search_tree:
def __init__(self):
self.root_node = None
def insert(self, value, curr_node):
if self.root_node == None:
self.root_node == node(value)
elif self.root_node < value:
if self.right_child == None:
self.right.child = value
else:
curr_node == self.right_child
if curr_node < value:
curr_node.right_child = node(value)
elif curr_node > value:
curr_node.left_child = node(value)
else:
print("Error! Value Already Exists!")
elif self.root_node > value:
if self.left_child == None:
self.left.child = value
else:
curr_node == self.left_child
if curr_node < value:
curr_node.right_child = node(value)
elif curr_node > value:
curr_node.left_child = node(value)
else:
print("Error! Value Already Exists!")
else:
print("Error! Value Already Exists!")
def fill_Tree(tree, num_elems = 100, max_int = 1000):
from random import randint
for x in range (num, elems):
curr_elem = randint(0, max_int)
tree.insert(curr_elem)
return tree
I have made a class Node to handle the nodes and a function insert that helps to insert the values. It check for the root node. If its there, it moves onto the leaf based on the values. If not, it adds the value as the root. The program keeps on checking for values and nodes and their differences (less than, greater than etc), just the ways a tree is supposed to function. The program executes, but nothing shows up. Not sure what I'm doing wrong though.
Any sort of help would be appreciated!
Thanks.
If that is your entire code, and if the input and execution is perfect, it would not show any result, because you are not printing any result.
You don't have an apparent main function to create an object of the class binar_search_tree.
The print statements that you have are only when there is an error. If everything works perfectly, your code doesn't print anything
You would need a method that can display the the tree
Currently, your insertion method is assigning values to the left or right children of the root, not traveling to a depth beyond those two nodes, should a value smaller than the left child or greater than the right child be found. Instead, create one class to store the value, left, and right child, along with the necessary insertion method. To determine if a value exists in the tree, it is cleaner to utilize __getitem__ with recursion:
def check_val(f):
def wrapper(cls, _val):
if _val in cls.__class__.seen:
raise ValueError(f"'{_val}' already in '{cls.__class__.__name__}'")
return f(cls, _val)
return wrapper
class Tree:
seen = []
def __init__(self, value=None):
self.left = None
self.value = value
self.right = None
def __lt__(self, _node):
return self.value < getattr(_node, 'value', _node)
#check_val
def insert_val(self, _val):
if self.value is None:
self.value = _val
self.__class__.seen.append(_val)
else:
if _val < self.value:
if self.left is None:
self.left = Tree(_val)
Tree.seen.append(_val)
else:
self.left.insert_val(_val)
else:
if self.right is None:
self.right = Tree(_val)
Tree.seen.append(_val)
else:
self.right.insert_val(_val)
def __getitem__(self, val):
if self.value == val:
return True
if val < self.value:
return getattr(self.left, '__getitem__', lambda _:False)(val)
return getattr(self.right, '__getitem__', lambda _:False)(val)
#classmethod
def load_tree(cls, size = 10):
_t = cls()
import random
for _ in range(size):
_t.insert_val(random.randint(1, 100))
return _t
To run:
t = Tree.load_tree()
print(t.__class__.seen)
#[82, 94, 33, 59, 73, 72, 96, 14, 58, 67]
for i in t.__class__.seen:
assert t[i]
print('all cases passed')
Output:
'all cases passed'

How to call upon a Binary Search Tree in an algorithm

I am attempting to create a simple version of spell check which takes a .txt file and compares whether each word is found in the dictionary or not. I have established functions that turn .txt files into lists and the dictionary into a list, but I am struggling calling upon my sorted binary search tree for the dictionary in my spell check function. Here is the class for BinarySearchTree followed by my spell checker function
class BinarySearchTree:
def __init__(self):
self.root = None
def insert(self,val):
if self.root == None:
self.root = BinaryNode(val)
else:
self.recursive_insert(root,val)
def recursive_insert(self,parent,val):
if parent.data < val:
if parent.right != None:
self.recursive_insert(parent.right,val)
else:
parent.right = BinaryNode(val)
else:
if parent.left != None:
self.recursive_insert(parent.left,val)
else:
parent.left = BinaryNode(val)
def dictionary_insert(self,text):
for word in text:
self.insert(word)
def search(self,val):
if self.recursive_search(self.root,val) != None:
return True
else:
return False
def recursive_search(self,parent,val):
if parent.data == val:
return parent
elif parent.data > val:
return self.recursive_search(parent.left,val)
else:
return self.recursive_search(parent.right,val)
Here is my spell checker function:
def spell_checker(text):
N = len(text)
misspelled = 0
for i in range(N):
if BinarySearchTree().search(text[i]) == True:
misspelled = misspelled
else:
misspelled = misspelled + 1
print text[i]
if misspelled == 0:
print "There are no spelling errors!"
Any help would be greatly appreciated.
When you first call recursive_search, you pass self.root as parent. However, in __init__, self.root was set to None. Therefore trying to access parent.data gives you an error, as None.data doesn't exist. You need to do a dictionary_insert, passing in a list of valid words, as part of your setup procedure, so that the tree actually has words in it:
dct = BinarySearchTree()
dct.dictionary_insert(valid_word_list)
You will also need to correct the last line of insert:
self.recursive_insert(self.root, val)
Just to fill this out in an answer:
The recursive_search call doesn't handle failure correctly:
def recursive_search(self,parent,val):
if parent.data == val:
return parent
elif parent.data > val:
return self.recursive_search(parent.left,val)
else:
return self.recursive_search(parent.right,val)
If the word isn't found in the tree at all, eventually this will be called with the parent argument set to None, and the statement if parent.data == val: will throw a NoneType exception.
The solution here is to return None when parent == None:
def recursive_search(self,parent,val):
if parent == None:
return None
if parent.data == val:
return parent
elif parent.data > val:
return self.recursive_search(parent.left,val)
else:
return self.recursive_search(parent.right,val)

Categories

Resources