I've been trying the recursive approach but been stuck for too long. I cant tell if it's my BST code that's wrong or my recursion.
Regardless of how many elements I put in my tree I still get the value 2 from my height function.
class Treenode:
def __init__(self, value = None, rchild = None, lchild = None):
self.value = value
self.rchild = rchild
self.lchild = lchild
class bin_tree:
def __init__(self):
self.root = None
def put(self, x):
if self.root is None:
self.root = Treenode(x)
return True
if self.exists(x) == True:
return False
p = self.root
while True:
if x < p.value:
if p.lchild is None:
p.lchild = Treenode(x)
return True
else:
p = p.lchild
elif x > p.value:
if p.rchild is None:
p.rchild = Treenode(x)
return True
else:
p = p.rchild
return
def exists(self, x):
p = self.root
while True and p != None:
if p.value == x:
return True
elif p.value > x and p.lchild != None:
p = p.lchild
elif p.value < x and p.rchild != None:
p = p.rchild
else:
return False
def isempty(self):
return self.root == None
def height(self):
def gh(enrot):
if enrot == None:
return 0
else:
return 1 + max(gh(enrot.lchild), gh(enrot.rchild))
return gh(self.root)
Example code:
from Bintree import *
p = bin_tree()
x = input()
for word in x.split():
p.put(word)
a = input()
if p.exists(a) is True:
print('Exists!')
else:
print('Does not exist!')
print(p.isempty())
print(p.height())
The height method is fine. In your put method, you stop without actually adding the element, so the height doesn't actually grow beyond 2:
def put(self, x):
...
while True:
if x < p.value:
...
elif x > p.value:
if p.rchild is None:
...
else:
p = p.rchild
return
# ^^^^^^ This shouldn't be here.
Related
I am writing a function that recursively finds the minimum and maximum values in a binary tree and returns a tuple (min, max). My code is returning the correct min and max for my test case but separately. Any advice on how to get it to return a tuple is appreciated! (As a note, I am not allowed to use LinkedBinaryTree functions that iterate over the tree for me but I attached the class I am currently using under my code)
My code
from LinkedBinaryTree import LinkedBinaryTree
def min_and_max(bin_tree):
if bin_tree is None:
raise Exception("Tree is empty")
def subtree_min_and_max(root):
minval = root.data
maxval = root.data
if (root.left is None and root.right is None):
temp = (minval, maxval)
return temp
elif (root.left is None):
ltemp = subtree_min_and_max(root.right)
if (ltemp[0] < minval):
minval= ltemp[0]
if (ltemp[1] > maxval):
maxval = ltemp[1]
temp = (minval, maxval)
return temp
elif (root.right is None):
subtree_min_and_max(root.left)
rtemp = subtree_min_and_max(root.right)
if (rtemp[0] < minval):
minval = rtemp[0]
if (rtemp[1] > maxval):
maxval = rtemp[1]
temp = (minval, maxval)
return temp
else:
ltemp = subtree_min_and_max(root.left)
rtemp = subtree_min_and_max(root.right)
print((min(root.data, ltemp[0], rtemp[0])))
print(max(root.data, ltemp[1], rtemp[1]))
temp = (min(root.data, ltemp[0], rtemp[0]), max(root.data, ltemp[1], rtemp[1]))
return temp
return subtree_min_and_max(bin_tree.root)
LinkedBinaryTree class
from ArrayQueue import ArrayQueue
class LinkedBinaryTree:
class Node:
def __init__(self, data, left=None, right=None):
self.data = data
self.parent = None
self.left = left
if (self.left is not None):
self.left.parent = self
self.right = right
if (self.right is not None):
self.right.parent = self
def __init__(self, root=None):
self.root = root
self.size = self.count_nodes()
def __len__(self):
return self.size
def is_empty(self):
return len(self) == 0
def count_nodes(self):
def subtree_count(root):
if (root is None):
return 0
else:
left_count = subtree_count(root.left)
right_count = subtree_count(root.right)
return 1 + left_count + right_count
return subtree_count(self.root)
def sum(self):
def subtree_sum(root):
if (root is None):
return 0
else:
left_sum = subtree_sum(root.left)
right_sum = subtree_sum(root.right)
return root.data + left_sum + right_sum
return subtree_sum(self.root)
def height(self):
def subtree_height(root):
if (root.left is None and root.right is None):
return 0
elif (root.left is None):
return 1 + subtree_height(root.right)
elif (root.right is None):
return 1 + subtree_height(root.left)
else:
left_height = subtree_height(root.left)
right_height = subtree_height(root.right)
return 1 + max(left_height, right_height)
if(self.is_empty()):
raise Exception("Tree is empty")
return subtree_height(self.root)
def preorder(self):
def subtree_preorder(root):
if (root is None):
pass
else:
yield root
yield from subtree_preorder(root.left)
yield from subtree_preorder(root.right)
yield from subtree_preorder(self.root)
def postorder(self):
def subtree_postorder(root):
if (root is None):
pass
else:
yield from subtree_postorder(root.left)
yield from subtree_postorder(root.right)
yield root
yield from subtree_postorder(self.root)
def inorder(self):
def subtree_inorder(root):
if (root is None):
pass
else:
yield from subtree_inorder(root.left)
yield root
yield from subtree_inorder(root.right)
yield from subtree_inorder(self.root)
def breadth_first(self):
if (self.is_empty()):
return
line = ArrayQueue()
line.enqueue(self.root)
while (line.is_empty() == False):
curr_node = line.dequeue()
yield curr_node
if (curr_node.left is not None):
line.enqueue(curr_node.left)
if (curr_node.right is not None):
line.enqueue(curr_node.right)
def __iter__(self):
for node in self.breadth_first():
yield node.data
My tester code
root = LinkedBinaryTree.Node(3)
T = LinkedBinaryTree(root)
a = LinkedBinaryTree.Node(2)
a.parent = root
root.left = a
b = LinkedBinaryTree.Node(7)
b.parent = root
root.right = b
c = LinkedBinaryTree.Node(9)
c.parent = a
a.left = c
d = LinkedBinaryTree.Node(5)
d.parent = c
c.left = d
e = LinkedBinaryTree.Node(1)
e.parent = c
c.right = e
f = LinkedBinaryTree.Node(8)
f.parent = b
b.left = f
g = LinkedBinaryTree.Node(4)
g.parent = b
b.right = g
print(min_and_max(T))
The tester code makes a tree that looks like
In subtree_min_and_max, when the case root.right is None, your code do:
subtree_min_and_max(root.left)
rtemp = subtree_min_and_max(root.right)
Which should be a single
rtemp = subtree_min_and_max(root.left)
as at this time, the sub-tree has empty right children, and the procedure should search for min and max in the left children.
**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)
So this is the node part of a singly linked list. I am not supposed to change the way it has been coded, but I dont know how this type of structure would work. Self.link cannot event be accessed to point towards another part of the list. Does anyone know how to work with such a Node class?
class Node:
def __init__(self, inval=None):
self.val = inval
if inval==None:
self.link = self
print (self)
def __str__(self):
if self.val == None:
return ''
else:
return str(self.val)
def __repr__(self):
return str(self)
Here is another implementation of the linked list, which has a slightly different styled node.
class LinkedList:
lock = 0
if lock == 0:
tempdata = None
def __init__(self, *args):
self.head = Node() # Node at the head of the list
self.current = None # Node currently pointed to by the iterator
self.count = 0
def insert(self, value):
NewNode =Node(value)
NewNode.link = self.head
self.head = NewNode
self.count += 1
def __iter__(self):
self.current = self.head
return self
def __next__(self):
self.current = LinkedList.tempdata
if LinkedList.lock == 0:
self.current = self.head
LinkedList.lock += 1
else:
pass
if self.current.value == None:
LinkedList.lock = 0
raise StopIteration
previous = self.current
self.current = self.current.link
LinkedList.tempdata = self.current
return previous
def __str__(self):
result = ''
self.current = self.head
while self.current.value is not None:
if self.current.link.value is None:
result += str(self.current.value)
else:
result += str(self.current.value) + ' -> '
self.current = self.current.link
return result
def search(self, value):
found = 0
temp = None
out= False
while found == 0:
try:
temp = LinkedList.__next__(self)
if temp.value == value:
found += 1
out = temp
except StopIteration:
pass
return out
def delete(self, value):
print ("hwta")
found = 0
temp = None
head = self.head
if head.value == value:
print ("Head")
if head.link.value != None:
self.head = head.link
else:
self.head = Node()
else:
while found == 0:
try:
temp = LinkedList.__next__(self)
if temp.link.value == value:
if temp.link.link.value == None:
temp.link = Node()
break
else:
temp.link = temp.link.link
print ("tails")
break
except StopIteration:
pass
def __repr__(self):
return str(self)
#a = Node()
#print(a) # 3
#b = Node("Hullo")
#print(b) # 'Hullo'
#lst = LinkedList()
#lst.insert(2)
#lst.insert(3)
#lst.insert(5)
#lst.insert(6)
#lst.insert(7)
#lst.insert(6)
#print(lst) # 5 -> 3 -> 2
#c = lst.search(2)
#print(c) # 3
#print(c.link) # 5
#lst.insert(2)
#print(lst.head.link.link) # 3
lst.delete(6)
print (lst)
#print(next(lst)) # should print 5, 3, 2 on separate lines
#lst.delete(2)
#print(lst) # 5 -> 3
#print(len(lst)) # 2
#for u in lst:
# print(u)
Nothing in the Node implementation that would prevent you from using it in a List class. Just pretend that the final three lines of Node.__init__() don't exist.
Here is one way to use the professor's Node in your List.
class Node:
def __init__(self, inval=None):
self.val = inval
if inval==None:
self.link = self
print (self)
def __str__(self):
if self.val == None:
return ''
else:
return str(self.val)
def __repr__(self):
return str(self)
class List:
def __init__(self):
self.head = None
def prepend(self, val):
head = Node(val)
head.link = self.head
self.head = head
def append(self, val):
if self.head is None:
self.prepend(val)
else:
p = self.head
while p.link is not None:
p = p.link
p.link = Node(val)
p.link.link = None
def __str__(self):
result = '<'
p = self.head
while p is not None:
result += str(p) + ', '
p = p.link
result += '>'
return result
l = List()
l.append(3)
l.prepend(2)
l.append(4)
l.prepend(1)
l.append(5)
print(str(l))
And here is the result:
<1, 2, 3, 4, 5, >
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.
class QNode:
def __init__(self, num):
self.prev = None
self.next = None
self.pageNumber = num
class Queue:
def __init__(self, num):
self.count = 0
self.front = None
self.rear = None
self.numberOfFrames = num
class Hash:
def __init__(self, num):
self.capacity = num
self.array = dict()
class LRU:
#staticmethod
def are_all_frames_full(q):
"returns a boolean value"
return q.count == q.numberOfFrames
#staticmethod
def is_queue_empty(q):
return q.rear == None
def de_queue(self, q):
if self.is_queue_empty(q):
return
if q.front == q.rear:
q.front = None
temp = q.rear
q.rear = q.rear.prev
if q.rear != None:
q.rear.next = None
q.count -= 1
def enqueue(self, q, h, pnum):
if self.are_all_frames_full(q):
h.array[q.rear.pageNumber] = None
self.de_queue(q)
temp = QNode(pnum)
temp.next = q.front
if self.is_queue_empty(q):
q.rear = q.front = temp
else:
q.front.prev = temp
q.front = temp
h.array[pnum] = temp
q.count += 1
def referencePage(self, q, h, pnum):
reqPage = h.array.get(pnum, None)
if reqPage == None:
self.enqueue(q, h, pnum)
elif reqPage != q.front:
reqPage.prev.next = reqPage.next
if reqPage.next != None:
reqPage.next.prev = reqPage.prev
if reqPage == q.rear:
q.rear = q.front
q.rear.next = None
reqPage.next = q.front
reqPage.prev = None
reqPage.next.prev = reqPage
q.front = reqPage
#staticmethod
def print_queue(q):
temp = q.front
print 'In the print queue method'
while(temp != q.rear):
print temp.pageNumber
temp = temp.next
q = Queue(4)
h = Hash(10)
l = LRU()
l.referencePage(q, h, 1)
l.referencePage(q, h, 2)
l.referencePage(q, h, 3)
l.referencePage(q, h, 1)
l.referencePage(q, h, 4)
l.referencePage(q, h, 5)
LRU.print_queue(q)
I am trying to implement LRU algorithm in Python. I am using Doubly linked list to maintain a queue which maintain the frames in the least recently used order.
The function referencePage implements the algorithm. After executing the algorithm, when I am trying to print the queue, the print_queue function is not printing anything. Dont know where it is going wrong.