Why is my helper method not activating recursively? - python

I have a Binary Search Tree and I am trying to trace recursively in order through the tree and append each key,value to a list. It is only appending the first key,value to the list and not going through the list in order. I pasted my code below, along with the test code I used at the bottom. Any help on how to get past this issue is super appreciated!
class TreeMap:
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.left = None
self.right = None
def __init__(self):
self.root = None
self.numsearches = 0
self.numcomparisons = 0
def add(self, newkey, newvalue):
newkey = newkey.lower()
if self.root == None:
self.root = TreeMap.Node(newkey, newvalue)
else:
TreeMap.add_helper(self.root, newkey, newvalue)
def add_helper(thisnode, newkey, newvalue):
if newkey <= thisnode.key:
if thisnode.left == None:
thisnode.left = TreeMap.Node(newkey, newvalue)
else:
TreeMap.add_helper(thisnode.left, newkey, newvalue)
else:
if thisnode.right == None:
thisnode.right = TreeMap.Node(newkey, newvalue)
else:
TreeMap.add_helper(thisnode.right, newkey, newvalue)
def print(self):
TreeMap.print_helper(self.root, 0)
def print_helper(somenode, indentlevel):
if somenode == None:
print(" "*(indentlevel),"---")
return
if not TreeMap.isleaf(somenode):
TreeMap.print_helper(somenode.right, indentlevel + 5)
print(" "*indentlevel + str(somenode.key) + ": " +str(somenode.value))
if not TreeMap.isleaf(somenode):
TreeMap.print_helper(somenode.left, indentlevel + 5)
def isleaf(anode):
return anode.left == None and anode.right == None
def listify(self, whichorder="in"):
'''
Returns a list consisting of all the payloads of the tree. (This returns a plain old Python List.)
The order of the payloads is determined by whichorder, which defaults to inorder.
The other possibilities are "pre" and "post".
If the tree is empty, return the empty list.
'''
assert type(whichorder) is str,"Whichorder is a string, and can only be pre, in or post"
assert whichorder in ["pre","in","post"],"Whichorder is a string, and can only be pre, in or post"
return TreeMap.listify_helper(self.root, whichorder)
def listify_helper(somenode, whichorder):
order_list = []
if somenode == None:
return order_list
elif somenode != None and whichorder == 'in':
TreeMap.listify_helper(somenode.left, 'in')
order_list.append(somenode.key+ '='+somenode.value)
TreeMap.listify_helper(somenode.right, 'in')
return order_list
TEST CODE:
import treemap
translator = treemap.TreeMap()
translator.add("cat", "Katze")
translator.add("bird", "Vogel")
translator.add("dog", "Hund")
translator.add("snake", "IDK")
translator.add("bear", "IDK")
translator.add("octopus", "Tintenfisch")
translator.add("horse", "Pferd")
translator.add("zebra", "IDK")
translator.print()
print("---------------------------------------------------")
print (translator.listify())

The problem is here:
def listify_helper(somenode, whichorder):
order_list = []
This function initialises its own local order_list every time it is invoked. Pass order_list as a parameter instead so that the same list is appended to by each recursive invocation.
Alternatively, append each element of the result of the recursive calls of listify_helper to order_list, although this approach could result in unneeded copying.

Related

Asking how to insert a new node to BST? Python

I am doing my practice, and the practice request create DSATreeNode and DSABinarySearchTree classes. The DSATreeNode is working fine, but when I use the function of insertRec. The insert function will call the insertRec that store the node in the right place. The problem comes is it is not storing and there is nothing in new node. Also the self._root is None, never insert anything into it.
Here's my code
class DSATreeNode:
def __init__(self, inKey, inValue):
self._key = inKey
self._value = inValue
self._left = self._right = None
class DSABinarySearchTree:
def __init__(self):
self._root = None
def find(self, key):
return self._findRec(key, self._root)
def _findRec(self, key, cur):
value = None
if cur == None: # Base case: not found
raise Exception("Key " + key + " not found")
elif key == cur._key: # Base case: found
value = cur._value
elif key < cur._key: # Go left (recursive)
value = self._findRec(key, cur._left)
else: # Go right(recursive)
value = self._findRec(key, cur._right)
return value
def insert(self, inKey, inValue):
return self.insertRec(inKey, inValue, self._root)
def insertRec(self, key, value, curNode):
createNode = DSATreeNode(key, value)
if curNode == None:
curNode = createNode
elif key < curNode._key:
curNode._left = self.insertRec(key, value, curNode._left)
else:
curNode._right = self.insertRec(key, value, curNode._right)
def getRoot(self):
return self._root._key, self._root._value
A few issues:
_insertRec does not return a node. It should have return curNode as its last statement.
There is no code that assigns a node to self._root. The insert method should assign like this: self._root = self.insertRec(inKey, inValue, self._root).
The error message generated in _findRec assumes that key is a string, but if it isn't, then it will fail. Better do raise Exception("Key " + str(key) + " not found") or raise Exception(f"Key {key} not found")
Not blocking, but _insertRec should not create a node when it still is going to make a recursive call. So move that first line into the first if block:
if curNode == None:
curNode = DSATreeNode(key, value)

Question on argument in functions for deserializing the string back into tree in Python

The question that I am asking here is based on www.dailycodingproblem.com
question 3:
"Given the root to a binary tree, implement serialize(root), which serializes the tree into a string, and deserialize(s), which deserializes the string back into the tree."
The code below is one of the solutions that I found and the question I want to ask is:-
For the deserialize function in line 42, when I pass an argument such as
def deserializer(node): which is followed by return deserializer(node), the output says "node not defined error" if I input any numbers eg: 1,3,2.
However, it works when I leave out the argument part empty that is def deserializer() followed by return deserializer()?
Your help would be much appreciated!
#must create a constructor every time we create a class eg: def __init__(self)
class Node:
def __init__(self, v):
self.left = None #none = empty state
self.right = None
self.value = v
class Tree:
def __init__(self):
self.root = None
def addNode(self, node, v1):
if node == None:
self.root = Node(v1)
#argument in Node need not have to be v
else:
if v1 < node.value:
#if 2nd value less than 1st value for example?
if not node.left:
node.left = Node(v1) #will not update value
else:
#if it is node.left,update value
self.addNode(node.left, v1)
else:
if not node.right:
node.right = Node(v1)
else:
self.addNode(node.right, v1)
def deserialize(s):
values = iter(s.split(','))
def deserializer(): #why putting def deserializer(node) gives me "node undefined error"?)
val = next(values)
if val == '?':
return None
else:
node = Node(int(val))
node.left = deserializer()
node.right = deserializer()
return node
return deserializer() #why putting return deserializer(node) gives me "node undefined error"?)
if __name__ == '__main__':
# Read input, numbers separated by commas
numbers = [int(n) for n in input().split(',')]
theTree = Tree()
for number in numbers:
theTree.addNode(theTree.root, number)
s2 = serialize(deserialize(s1))
print(s2)

In Order Traversal AVL Tree: Name not defined

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

python create a binary search tree using existing function

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.

Use a function built outside the class on an object in Python?

I have a class
class List:
def __init__(self,head,tail):
self.head = head
self.tail = tail
def cons(self,item):
return List(item,self)
def isEmpty(self):
return self.head == None
def display(self):
s = "["
first = True
list = self
while not list.isEmpty():
if not first:
s=s+","
first = False
s=s+str(list.head)
list = list.tail
s=s+"]"
return s`
which creates a List object. I have a function (not sure if it works yet);
def sorted(list):
sort = False
i = 0
while i < range(len(list))+1:
if list[i] < list[i+1]:
sort = True
return sort
else:
return sort
and I want to run this function on the List object without adding another method to the class. I know if this was in the class it would just be List.sorted() but how can I run this function on the object without it being the objects method?
sorted(List) doesn't seem to work either. Help please.
Please, please, PLEASE: don't use sorted as a function name. There is a standard (built-in) function sorted() already, that returns a sorted version of an iterable.
Given that your code just checks to see if the List is in order, perhaps you could call it in_order or ordered or is_ascending instead?
That said, let's try to get your code working:
class Node:
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def __str__(self):
return str(self.data)
class List:
def __init__(self, head:Node=None, tail:Node=None):
self.head = tail if head is None else head
self.tail = head if tail is None else tail
def cons(self, node:Node):
node.next = self.head
return List(node, self.tail)
def isEmpty(self):
return self.head == None
def display(self):
return str(self)
def __str__(self):
result = "["
first = True
n = self.head
while n is not None:
if not first:
result += ", "
result += str(n)
if n == self.tail:
break
n = n.next
first = False
result += "]"
return result
def ascendingp(self) -> bool:
n = self.head
last = None
while last != self.tail:
if last is not None and not last.data < n.data:
return False
last = n
n = n.next
return True
tests = (
(1,2,3),
(1,3,2),
(),
)
for t in tests:
last = None
first = None
for i in reversed(t):
n = Node(data=i)
first = n if first is None else first
n.next = last
last = n
l = List(head=last, tail=first)
print(str(l), "Ascending?", l.ascendingp())

Categories