I am making a binary tree with a very large list, almost 10000 objects. The issue is that I get a maximum recursion error due to the huge size. It happens specifically in the binarytree class where TreeNode is being called to create new objects. I am unsure how to implement this without recursion, as it seems to be the easiest way to implement the code.
class TreeNode:
def __init__(self,key,val,left=None,right=None,parent=None):
self.key = key
self.payload = val
self.leftChild = left
self.rightChild = right
self.parent = parent
def hasLeftChild(self):
return self.leftChild
def hasRightChild(self):
return self.rightChild
def isLeftChild(self):
return self.parent and self.parent.leftChild == self
def isRightChild(self):
return self.parent and self.parent.rightChild == self
def isRoot(self):
return not self.parent
def isLeaf(self):
return not (self.rightChild or self.leftChild)
def hasAnyChildren(self):
return self.rightChild or self.leftChild
def hasBothChildren(self):
return self.rightChild and self.leftChild
Binary Tree:
class BinarySearchTree:
def __init__(self):
self.root = None
self.size = 0
def length(self):
return self.size
def __len__(self):
return self.size
def put(self,key,val):
if self.root:
self._put(key,val,self.root)
else:
self.root = TreeNode(key,val)
self.size = self.size + 1
def _put(self,key,val,currentNode):
if key < currentNode.key:
if currentNode.hasLeftChild():
self._put(key,val,currentNode.leftChild)
else:
currentNode.leftChild = TreeNode(key,val,parent=currentNode)
else:
if currentNode.hasRightChild():
self._put(key,val,currentNode.rightChild)
else:
currentNode.rightChild = TreeNode(key,val,parent=currentNode)
def __setitem__(self,k,v):
self.put(k,v)
def get(self,key):
if self.root:
res = self._get(key,self.root)
if res:
return res.payload
else:
return None
else:
return None
def _get(self,key,currentNode):
if not currentNode:
return None
elif currentNode.key == key:
return currentNode
elif key < currentNode.key:
return self._get(key,currentNode.leftChild)
else:
return self._get(key,currentNode.rightChild)
def __getitem__(self,key):
return self.get(key)
def __contains__(self,key):
if self._get(key,self.root):
return True
else:
return False
It is fairly simple to convert your recursive methods to iterative ones, e.g.:
def get(self, key):
node = self.root
while node:
if node.key == key:
return node.payload
elif key < node.key:
node = node.leftChild
else:
node = node.rightChild
return None
def put(self, key, val):
if not self.root:
self.root = TreeNode(key, val)
else:
self._put(key, val, self.root)
self.size = self.size + 1
def _put(self, key, val, currentNode):
while True:
if key < currentNode.key:
if currentNode.hasLeftChild():
currentNode = currentNode.leftChild
else:
currentNode.leftChild = TreeNode(key, val, parent=currentNode)
break
else:
if currentNode.hasRightChild():
currentNode = currentNode.rightChild
else:
currentNode.rightChild = TreeNode(key, val, parent=currentNode)
break
This gets rid of any recursion (limits) and is just as readable.
Related
I got the problem to find the height from a partially completed code sample of BST implementation as below.
class BST:
class Node:
def __init__(self, key, left=None, right=None):
self.key = key
self.left = left
self.right = right
def __iter__(self):
if self.left:
yield from self.left
yield self.key
if self.right:
yield from self.right
def __init__(self, root=None):
self.root = root
def __iter__(self):
if self.root:
yield from self.root
def insert(self, key):
self.root = self._insert(self.root, key)
def _insert(self, r, key):
if r is None:
return self.Node(key)
elif key < r.key:
r.left = self._insert(r.left, key)
elif key > r.key:
r.right = self._insert(r.right, key)
else:
pass
return r
def print(self):
self._print(self.root)
def _print(self, r):
if r:
self._print(r.left)
print(r.key, end=' ')
self._print(r.right)
def contains(self, k):
n = self.root
while n and n.key != k:
if k < n.key:
n = n.left
else:
n = n.right
return n is not None
def size(self):
return self._size(self.root)
def _size(self, r):
if r is None:
return 0
else:
return 1 + self._size(r.left) + self._size(r.right)
I tried to implement "def height(self): " method, referencingBinary search tree
I tried left and right nodes as below
for node in self.root.__iter__():
print(node)
But, I was unable to understand how to work with generators and implement this height method.Hope your support. Thanks in advance.
**deleting the root(the first node i enter strong text) node shows the error 'TreeNode' object has no attribute 'findSuccessor'
when i try to delete the first node that is inserted it shows an attribute eroor
but the nodes that are inserted later get delete
can you tell me what is wrong with code **
class TreeNode:
def __init__(self,key,val,left=None,right=None,parent=None):
self.key = key
self.payload = val
self.leftChild = left
self.rightChild = right
self.parent = parent
def hasLeftChild(self):
return self.leftChild
def hasRightChild(self):
return self.rightChild
def isLeftChild(self):
return self.parent and self.parent.leftChild == self
def isRightChild(self):
return self.parent and self.parent.rightChild == self
def isRoot(self):
return not self.parent
def isLeaf(self):
return not (self.rightChild or self.leftChild)
def hasAnyChildren(self):
return self.rightChild or self.leftChild
def hasBothChildren(self):
return self.rightChild and self.leftChild
def replaceNodeData(self,key,value,lc,rc):
self.key = key
self.payload = value
self.leftChild = lc
self.rightChild = rc
if self.hasLeftChild():
self.leftChild.parent = self
if self.hasRightChild():
self.rightChild.parent = self
class BinarySearchTree:
def __init__(self):
self.root = None
self.size = 0
def length(self):
return self.size
def __len__(self):
return self.size
def put(self,key,val):
if self.root:
self._put(key,val,self.root)
else:
self.root = TreeNode(key,val)
self.size = self.size + 1
def _put(self,key,val,currentNode):
if key < currentNode.key:
if currentNode.hasLeftChild():
self._put(key,val,currentNode.leftChild)
else:
currentNode.leftChild = TreeNode(key,val,parent=currentNode)
else:
if currentNode.hasRightChild():
self._put(key,val,currentNode.rightChild)
else:
currentNode.rightChild = TreeNode(key,val,parent=currentNode)
def __setitem__(self,k,v):
self.put(k,v)
def get(self,key):
if self.root:
res = self._get(key,self.root)
if res:
return res.payload
else:
return None
else:
return None
def _get(self,key,currentNode):
if not currentNode:
return None
elif currentNode.key == key:
return currentNode
elif key < currentNode.key:
return self._get(key,currentNode.leftChild)
else:
return self._get(key,currentNode.rightChild)
def __getitem__(self,key):
return self.get(key)
def __contains__(self,key):
if self._get(key,self.root):
return True
else:
return False
def delete(self,key):
if self.size > 1:
nodeToRemove = self._get(key,self.root)
if nodeToRemove:
self.remove(nodeToRemove)
self.size = self.size-1
else:
raise KeyError('Error, key not in tree')
elif self.size == 1 and self.root.key == key:
self.root = None
self.size = self.size - 1
else:
raise KeyError('Error, key not in tree')
def __delitem__(self,key):
self.delete(key)
def spliceOut(self):
if self.isLeaf():
if self.isLeftChild():
self.parent.leftChild = None
else:
self.parent.rightChild = None
elif self.hasAnyChildren():
if self.hasLeftChild():
if self.isLeftChild():
self.parent.leftChild = self.leftChild
else:
self.parent.rightChild = self.leftChild
self.leftChild.parent = self.parent
else:
if self.isLeftChild():
self.parent.leftChild = self.rightChild
else:
self.parent.rightChild = self.rightChild
self.rightChild.parent = self.parent
def findSuccessor(self):
succ = None
if self.hasRightChild():
succ = self.rightChild.findMin()
else:
if self.parent:
if self.isLeftChild():
succ = self.parent
else:
self.parent.rightChild = None
succ = self.parent.findSuccessor()
self.parent.rightChild = self
return succ
def findMin(self):
current = self
while current.hasLeftChild():
current = current.leftChild
return current
def remove(self,currentNode):
if currentNode.isLeaf(): #leaf
if currentNode == currentNode.parent.leftChild:
currentNode.parent.leftChild = None
else:
currentNode.parent.rightChild = None
elif currentNode.hasBothChildren(): #interior
succ = currentNode.findSuccessor()
succ.spliceOut()
currentNode.key = succ.key
currentNode.payload = succ.payload
else: # this node has one child
if currentNode.hasLeftChild():
if currentNode.isLeftChild():
currentNode.leftChild.parent = currentNode.parent
currentNode.parent.leftChild = currentNode.leftChild
elif currentNode.isRightChild():
currentNode.leftChild.parent = currentNode.parent
currentNode.parent.rightChild = currentNode.leftChild
else:
currentNode.replaceNodeData(currentNode.leftChild.key,
currentNode.leftChild.payload,
currentNode.leftChild.leftChild,
currentNode.leftChild.rightChild)
else:
if currentNode.isLeftChild():
currentNode.rightChild.parent = currentNode.parent
currentNode.parent.leftChild = currentNode.rightChild
elif currentNode.isRightChild():
currentNode.rightChild.parent = currentNode.parent
currentNode.parent.rightChild = currentNode.rightChild
else:
currentNode.replaceNodeData(currentNode.rightChild.key,
currentNode.rightChild.payload,
currentNode.rightChild.leftChild,
currentNode.rightChild.rightChild)
'''
Simple map ADT implementation using BST
'''
#! /usr/bin/env python3
import os
class TreeNode:
def __init__(self, key, data, left, right, parent):
self.key = key
self.value = data
self.leftchild = left
self.rightchild = right
self.parent = parent
def insertnode(self, key, value):
if key <= self.key:
#left child
if self.leftchild is not None:
self.leftchild.insertnode(key, value)
else:
self.leftchild = TreeNode(key=key, data=value, left=None, right=None, parent=self)
else:
if self.rightchild is not None:
self.rightchild.insertnode(key, value)
else:
self.rightchild = TreeNode(key=key, data=value, left=None, right=None, parent=self)
def displaynode(self):
if self.key is not None:
print(self.key, ":", self.value)
if self.leftchild is not None:
self.leftchild.displaynode()
if self.rightchild is not None:
self.rightchild.displaynode()
def search(self, key):
if self is None:
return None
elif key == self.key:
return self
elif key < self.key:
self.leftchild.search(key)
else:
self.rightchild.search(key)
def deletekey(self, key):
keyNode = self.search(key)
print(keyNode)
if keyNode is None:
raise KeyError('Key not found in the tree.')
else:
if keyNode.leftchild is None and keyNode.rightchild is None:
keyNode = None
elif keyNode.leftchild is not None and keyNode.rightchild is not None:
if keyNode.parent is None:
self.root = keyNode.leftchild
else:
keyNode.rightchild.parent = keyNode.leftchild
keyNode.parent.leftchild = keyNode.leftchild
keyNode = None
elif keyNode.leftchild is not None:
keyNode.parent.leftchild = keyNode.leftchild
keyNode = None
elif keyNode.rightchild is not None:
keyNode.parent.leftchild = keyNode.rightchild
keyNode = None
return True
class binaryTree():
def __init__(self):
self.root = None
self.size = 0
def length(self):
return self.size
def __len__(self):
return self.size
def insert(self, key, value):
if self.root is None:
self.root = TreeNode(key=key, data=value, left=None, right=None, parent=self)
self.size = self.size + 1
else:
self.root.insertnode(key, value)
self.size = self.size + 1
def display(self):
if self.root is None:
return None
else:
#currentNode = self.root
self.root.displaynode()
def __setitem__(self, key, value):
self.root.insertnode(key, value)
self.size = self.size + 1
def __contains__(self, item):
if self.root.search(item) is not None:
return True
else:
return False
def find(self, key):
if self.root.search(key) is not None:
return True
else:
return False
def __delitem__(self, key):
if self.root.deletekey(key, self.root):
self.size = self.size - 1
if __name__ == "__main__":
tree = binaryTree()
tree.insert(100, 'a')
tree.insert(50, 'b')
tree.insert(200, 'c')
#tree.insert(25, 'd')
tree[25] = 'd'
print(tree.size)
tree.display()
if 50 in tree:
print(f'{50} found')
else:
print(f'{50} not found')
print(tree.find(50))
tr = TreeNode(key = 100, data='a', left=None, right=None parent=None)
print(tr.search(100))
#del tree[50]
#tree.display()
I am looking for key 50 in the tree by overriding the 'in' using contains and the key is there in the tree which and it returns 'self' object from the search method in the class TreeNode.
However, when its evaluated in the contains or find() in the binary tree class its always None. Not sure what Iam missing here.
I'm implementing a (recursive) binary search tree and I can't get the size function working. This is my code so far:
class BinarySearchTreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def __str__(self):
return str(self.data)
def add(self, data):
if self.data == data:
return False
elif data < self.data:
if self.left:
return self.left.add(data)
else:
self.left = BinarySearchTreeNode(data)
return True
else:
if self.right:
return self.right.add(data)
else:
self.right = BinarySearchTreeNode(data)
return True
def contains(self, data):
if self.data == data:
return True
elif self.data > data:
if self.left:
return self.left.contains(data)
else:
return False
else:
if self.right:
return self.right.contains(data)
else:
return False
def size(self):
if self.left and self.right:
return 1 + self.left.size() + self.right.size()
elif self.left:
return 1 + self.left.size()
elif self.right:
return 1 + self.right.size()
else:
return 1
class BinarySearchTree:
def __init__(self):
self.root = None
def add(self, data):
if not self.root:
self.root = BinarySearchTreeNode(data)
return True
else:
return self.root.add(data)
def contains(self, data):
if self.root:
return self.root.contains(data)
else:
return False
def clear(self):
self.root = None
def size(self):
if self.root is None:
return 0
else:
return self.root.size()
bst = BinarySearchTree()
bst.add(3)
bst.add(24)
bst.add(7)
bst.add(15)
bst.add(2)
bst.add(19)
bst.size()
I want the size function to be called from the BinarySearchTree class but executed via the BinarySearchTreeNode class. I have tried everything I can think of, but nothing works. What am I doing wrong?
What is this?
class BinarySearchTreeNode:
self.data = data
self.left = None
self.right = None
This is not an initializing process you're doing there mate. Try the following:
class BinarySearchTreeNode:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
Even checked it for you:
In[1]:
bst = BinarySearchTree()
bst.add(3)
bst.add(24)
bst.add(7)
bst.add(15)
bst.add(2)
bst.add(19)
bst.size()
Out[2]: 6
I am trying to use BFS to search through a tree with three letter words and find the way in between a given start and end word and print the way in between. The printing is supposed to be done with a recursive function.
I keep getting this error:
RecursionError: maximum recursion depth exceeded while calling a Python object
and an infinite loop with the endword can anyone see whats wrong? (I copied my imported classes as well).
from array import array
class Node1:
#håller koll på värdena
def __init__(self, data, next = None):
self.data = data
self.next = next
def __str__(self):
if self.data.parent == None:
return None
else:
print(self.data.parent)
return str(self.data.parent)
def __str__(self):
return str(self.data.word)
class Queue:
def __init__(self):
self.first = None
self.last = None
def enqueue(self,x):
"""Stoppar in x sist i kön """
x = Node1(x)
if self.first == None: # Om kön är tom
self.first = self.last = x
else: # om kön inte är tom
self.last.next = x
self.last = x
def dequeue(self):
first = self.first
self.first = self.first.next
#if self.first == None:
# self.last=None
return first
def isEmpty(self):
if self.first == None:
xx = True
else:
xx = False
#print('I IsEmpty: Första elementet i listan:',self.first)
#print('I IsEmpty: Sista elementet i listan:',self.last)
return xx
def __str__(self):
node=self.first
node_strang = 'Efter trolleriet får man: '
while node != None:
node_strang += str(node)
node = node.next
return node_strang
class Node:
'''Nodklass med rekursiva metoder som anropas i Bintree-klassen'''
def __init__(self, word):
self.word = word
self.left = None
self.right = None
def insert(self, new_word):
if self.word == new_word:
return False
elif new_word < self.word:
if self.left:
return self.left.insert(new_word)
else:
self.left = Node(new_word)
return True
else:
if self.right:
return self.right.insert(new_word)
else:
self.right = Node(new_word)
return True
def find(self, new_word):
if self.word == new_word:
return True
elif new_word < self.word:
if self.left:
return self.left.find(new_word)
else:
return False
else:
if self.right:
return self.right.find(new_word)
else:
return False
def preorder(self):
if self:
print(self.word)
if self.left:
self.left.preorder()
if self.right:
self.right.preorder()
def postorder(self):
if self:
if self.left:
self.left.postorder()
if self.right:
self.right.postorder()
print(self.word)
def inorder(self):
if self:
if self.left:
self.left.inorder()
print(self.word)
if self.right:
self.right.inorder()
from linkedQFile import Queue,Node1
from bintreeFile import Node
import string
class Bintree:
def __init__(self):
self.root = None
def put(self, new_word):
if self.root:
return self.root.insert(new_word)
else:
self.root = Node(new_word)
return True
def __contains__(self, new_word):
if self.root:
return self.root.find(new_word)
else:
return False
class ParentNode:
def __init__(self, word, parent = None):
self.word = word
self.parent = parent
def maketree():
svenska = Bintree()
gamla = Bintree()
with open('word3.txt', 'r') as ordfil:
for rad in ordfil:
ord = rad.strip()
if ord in svenska:
gamla.put(ord)
svenska.put(ord)
ordfil.close()
return svenska,gamla
def writechain(kidzen, paronen):
if paronen is not None:
print(kidzen)
writechain(kidzen, paronen)
else:
pass
def countchain(barn_obj):
if barn_obj.parent==None:
return 0
else:
return 1+countchain(barn_obj.parent)
def makechildren(nod, q, gamla, svenska):
for i in range(3):
bokstavslista = list(nod.data.word)
alfabetslista = list(string.ascii_lowercase) + ['å', 'ä', 'ö']
for bokstav in alfabetslista:
bokstavslista[i] = bokstav
barn = ''.join(bokstavslista)
if barn in svenska:
barn_obj = ParentNode(barn, nod.data)
#print('parent to', barn, 'is', str(barn_obj.parent))
if barn not in gamla:
#print("i makechildren: barn = ", barn)
q.enqueue(barn_obj)
gamla.put(barn_obj.word)
def main():
(svenska,gamla) = maketree()
q=Queue()
start = input('Startord:')
slut = input('Slutord:')
startord= ParentNode(start, parent=None)
q.enqueue(startord)
while not q.isEmpty():
nod = q.dequeue()
makechildren(nod, q, gamla, svenska)
nod_for=nod.data
kidzen=nod_for.word
paronen=nod_for.parent
#print ('word =', kidzen)
#print ('parent =', paronen)
if q.isEmpty():
print('Det finns ingen väg till', slut)
break
elif kidzen==slut:
writechain(kidzen, paronen)
print('Det finns en väg till', slut)
break
main()
In your writechain function you are not walking a tree.
You keep recursively calling it with the same arguments. That will continue until you reach the recursion limit.