Output BST in Nested Form - python

I have to do inOrder, levelOrder, preOrder, and postOrder transversal of a BST.
Here's a small sample with in order
class BSTNode:
def __init__ (self, x, L=None, R=None):
self.data = x
self.left = L
self.right = R
class BST:
def __init__ (self):
self.root = None
def insert (self, x):
def recurse (p):
if x<p.data:
if p.left==None:
p.left = BSTNode (x)
else:
recurse (p.left)
else:
if p.right==None:
p.right = BSTNode (x)
else:
recurse (p.right)
if self.root==None:
self.root = BSTNode(x)
else:
recurse (self.root)
def inOrder (self):
print ("InOrder: ", end="")
def recurse(node):
if node != None:
recurse(node.left)
print(node.data,end = " ")
recurse(node.right)
recurse(self.root)
print( )
def main( ):
T = BST( )
L = eval(input ("Enter list: "))
for x in L:
T.insert(x)
T.inOrder( )
if __name__ == '__main__':
main( )
Does anyone know how I should approach this? I have separate methods (Python) for each traversal right now and I am doing the level-order algorithm using a queue.

Recurse as you did in BST.inOrder, but instead of printing them, make (and return) a list recursively. And it seems more sense to put recusive functions in BSTNode.
class BSTNode:
def __init__(self, x, L=None, R=None):
self.data = x
self.left = L
self.right = R
def inOrder(self):
ret = []
if self.left: ret.append(self.left.inOrder())
ret.append(self.data)
if self.right: ret.append(self.right.inOrder())
return ret
def preOrder(self):
ret = []
ret.append(self.data)
if self.left: ret.append(self.left.preOrder())
if self.right: ret.append(self.right.preOrder())
return ret
def postOrder(self):
ret = []
if self.left: ret.append(self.left.postOrder())
if self.right: ret.append(self.right.postOrder())
ret.append(self.data)
return ret
class BST:
def __init__(self):
self.root = None
def insert(self, x):
def recurse(p):
if x<p.data:
if p.left==None:
p.left = BSTNode(x)
else:
recurse(p.left)
else:
if p.right==None:
p.right = BSTNode(x)
else:
recurse(p.right)
if self.root==None:
self.root = BSTNode(x)
else:
recurse(self.root)
T = BST( )
for x in [5,3,7,2,4,6,8]:
T.insert(x)
print(T.root.inOrder())
print(T.root.preOrder())
print(T.root.postOrder())
output:
[[[2], 3, [4]], 5, [[6], 7, [8]]]
[5, [3, [2], [4]], [7, [6], [8]]]
[[[2], [4], 3], [[6], [8], 7], 5]
I'll leave Level-Order traversal for your exercise.

Related

Binary search tree with python generators

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.

How does a node with return self work?(Python)

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 keep getting this error:RecursionError: maximum recursion depth exceeded while calling a Python object

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.

Level Order Traversal - Tree

I need to define a function called level_order_travel which takes a tree as an output, a, and prints a list of all the nodes in the list in level order.
The following code here shows this:
def create_tree(node_list, index=1):
if index >= len(node_list) or node_list[index] is None:
return None
d = node_list[index]
l = index * 2
r = l + 1
tree = BinaryTree(d)
tree.set_left(create_tree(node_list, l))
tree.set_right(create_tree(node_list, r))
return tree
def level_order_travel(a):
###
def test():
list_of_leaves = [None, 10, 5, 15, None, None, 11, 22]
my_tree = create_tree(list_of_leaves )
print("Breadth first =", level_order_travel(my_tree))
test()
This is my BinaryTree class:
class BinaryTree:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def get_left(self):
return self.left
def get_right(self):
return self.right
def set_left(self, tree):
self.left = tree
def set_right(self, tree):
self.right = tree
def set_data(self, data):
self.data = data
def get_data(self):
return self.data
def create_string(self, spaces):
info = ' ' * spaces + str(self.data)
if self.left != None:
info += '\n(l)' + self.left.create_string(spaces+4)
if not self.right == None:
info += '\n(r)' + self.right.create_string(spaces+4)
return info
def __str__(self):
representation = self.create_string(0)
return representation
This is my Queue class:
class Queue:
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def enqueue(self, item):
self.items.insert(0,item)
def dequeue(self):
return self.items.pop()
def size(self):
return len(self.items)
def peek(self):
return self.items[self.size() - 1]
This is my attempt so far:
def level_order_travel(a):
root = a.get_data()
q = Queue()
q.enqueue(root)
list_of_leaves = []
if root is None:
return []
else:
if a.get_left() is not None:
q.enqueue(a.get_left().get_data())
if a.get_right() is not None:
q.enqueue(a.get_right().get_data())
while q.is_empty() == False:
list_of_leaves.append(q.dequeue())
return list_of_leaves
This should produce the following output:
[10, 5, 15, 11, 22]
but instead it produces the following output:
[10, 5, 15]
Any help is appreciated. Thank you.
Modify your bfs traversal function to keep track of the visited nodes, it should work for any graph (not only the acyclic ones as trees):
def breadth_first_traversal(a):
if a is None:
return []
visited = set([])
q = Queue()
q.enqueue(a)
list_of_leaves = []
while not q.is_empty():
a = q.dequeue()
visited.add(a)
child = a.get_left()
if child is not None and not child in visited:
q.enqueue(child)
child = a.get_right()
if child is not None and not child in visited:
q.enqueue(child)
list_of_leaves.append(a.get_data())
return list_of_leaves
test()
# ('Breadth first =', [10, 5, 15, 11, 22])
Also, if you want to use the implementation only for trees then you can further simplify (you don't need to keep track of the visited nodes, since each node is guaranteed to be visited only once, for each node has only one parent):
def breadth_first_traversal(a): # only for trees
if a is None:
return []
q = Queue()
q.enqueue(a)
list_of_leaves = []
while not q.is_empty():
a = q.dequeue()
child = a.get_left()
if child is not None:
q.enqueue(child)
child = a.get_right()
if child is not None:
q.enqueue(child)
list_of_leaves.append(a.get_data())
return list_of_leaves

binary tree add left and add right nodes not adding

I'm reading the following data as part of an assignment into a binary tree (not a strict binary search tree):
5
4 1 2
2 3 4
5 -1 -1
1 -1 -1
3 -1 -1
They're being read into three lists in python self.key, self.left and self.right where the first line has the integer n is the number of nodes. The next n lines are key, left, right. Where left is the key of the left child of the parent is key[left] and likewise the key of the right child is key[right], so for example the first line is the key of 4 is the root and key[1] meaning 2 is the left child of 4 and key[2] meaning 5 is the right child of 4 and so on and -1 for left and right means this key is a leaf:
Tree structure for this example
The problem is the left and right children of the root are being added but none of the children of these are being added. Am I correctly adding nodes to the tree? I cannot just add them based on value of the key because it's not a strict binary search tree as some other examples make clear, such as root = 0 and left child = 70 and right child = 20. The output of inOrder traversal is 2 4 5 (should be 1 2 3 4 5) which leads me to believe I'm not adding the further nodes. Any help on the adding methods would be appreciated...
import sys, threading
sys.setrecursionlimit(10**6) # max depth of recursion
threading.stack_size(2**27) # new thread will get stack of such size
class Node:
def __init__(self, val):
self.l = None
self.r = None
self.v = val
class Tree:
def __init__(self):
self.root = None
def getRoot(self):
return self.root
def add_root(self, val):
if(self.root is None):
self.root = Node(val)
def add_left(self, val, node):
if(node.l is None):
node.l = Node(val)
def add_right(self, val, node):
if(node.r is None):
node.r = Node(val)
def deleteTree(self):
# garbage collector will do this for us.
self.root = None
def inOrder(self):
self.result = []
if(self.root is not None):
self._inOrder(self.root, self.result)
return self.result
else:
print('root is None')
def _inOrder(self, node, result):
if(node != None):
self._inOrder(node.l, self.result)
self.result.append(node.v)
self._inOrder(node.r, self.result)
def read(self):
self.n = int(sys.stdin.readline())
self.key = [0 for i in range(self.n)]
self.left = [0 for i in range(self.n)]
self.right = [0 for i in range(self.n)]
for i in range(self.n):
[a, b, c] = map(int, sys.stdin.readline().split())
self.key[i] = a
self.left[i] = b
self.right[i] = c
#adding root
self.add_root(self.key[0])
if self.left[0] != -1:
#add left of root
self.add_left(self.key[self.left[0]], self.root)
if self.right[0] != -1:
#add right of root
self.add_right(self.key[self.right[0]], self.root)
#where it is not adding left and right nodes
for i in range(1, self.n):
if self.left[i] != -1:
# adding the other left nodes
self.add_left(self.key[self.left[i]], Node(self.key[i]))
if self.right[i] != -1:
# adding the other right nodes
self.add_right(self.key[self.right[i]], Node(self.key[i]))
def main():
tree = Tree()
tree.read()
print(" ".join(str(x) for x in tree.inOrder()))
#print(" ".join(str(x) for x in tree.preOrder()))
#print(" ".join(str(x) for x in tree.postOrder()))
threading.Thread(target=main).start()
Thanks I got it to work - I added the nodes Node(key[i]) to a dictionary and self.nodes[val] = [node, node.l, node.r] and when adding the left and recursively searched the dictionary for inOrder, preOrder and postOrder tree traversals.
class Node:
def __init__(self, val):
self.l = None
self.r = None
self.v = val
class Tree:
def __init__(self):
self.root = None
self.nodes = {}
def getRoot(self):
return self.root
def add_root(self, val):
if(self.root is None):
self.root = Node(val)
self.nodes[val] = [self.root,-1,-1]
def add_left(self, val, node):
if(node.l is None):
node.l = Node(val)
self.nodes[node.v][1] = node.l
def add_right(self, val, node):
if(node.r is None):
node.r = Node(val)
self.nodes[node.v][2] = node.r
def inOrder(self):
self.result = []
if(self.root is not None):
self._inOrder(self.root, self.result)
return self.result
else:
print('root is None')
def _inOrder(self, node, result):
if(node is not None):
try:
self._inOrder(self.nodes[node.v][1], self.result)
except (IndexError, AttributeError):
pass
self.result.append(node.v)
try:
self._inOrder(self.nodes[node.v][2], self.result)
except (IndexError, AttributeError):
pass
def preOrder(self):
self.result = []
if(self.root is not None):
self._preOrder(self.root, self.result)
return self.result
else:
print('root is None')
def _preOrder(self, node, result):
if(node is not None):
self.result.append(node.v)
try:
self._preOrder(self.nodes[node.v][1], self.result)
except (IndexError, AttributeError):
pass
try:
self._preOrder(self.nodes[node.v][2], self.result)
except (IndexError, AttributeError):
pass
def postOrder(self):
self.result = []
if(self.root is not None):
self._postOrder(self.root, self.result)
return self.result
else:
print('root is None')
def _postOrder(self, node, result):
if(node is not None):
try:
self._postOrder(self.nodes[node.v][1], self.result)
except (IndexError, AttributeError):
pass
try:
self._postOrder(self.nodes[node.v][2], self.result)
except (IndexError, AttributeError):
pass
self.result.append(node.v)
def read(self):
self.n = int(sys.stdin.readline())
self.key = [0 for i in range(self.n)]
self.left = [0 for i in range(self.n)]
self.right = [0 for i in range(self.n)]
for i in range(self.n):
[a, b, c] = map(int, sys.stdin.readline().split())
self.key[i] = a
self.left[i] = b
self.right[i] = c
#adding root
self.add_root(self.key[0])
for i in range(1, self.n):
self.nodes[self.key[i]] = [Node(self.key[i]),-1,-1]
for i in range(0, self.n):
if self.left[i] != -1:
# adding the other left nodes
self.add_left(self.key[self.left[i]], self.nodes[self.key[i]][0])
if self.right[i] != -1:
# adding the other right nodes
self.add_right(self.key[self.right[i]], self.nodes[self.key[i]][0])

Categories