How to find the minimum, and maximum value within a Binary Tree - python

++ EDIT ++
Thanks to all of you, I have taken many compartments to get the code to finally working.
Here's the full code overview
class Node:
# Binary Roots: Left and Right, initiating data
def __init__(self, data):
# Creating an object, Data, to be used for inputs
self.data = data
# The objects are defined as None, which creates an empty space for input
self.left = None
self.right = None
Define Binary Tree Class:
class BinaryTree:
# Defining Roots as Nodes, initiating at the same time.
def __init__(self, rootdata):
# Declaring roots as new nodes which uses root data
self.root = Node(rootdata)
Defining FindMax, which will find the maximum value in a binary tree, then return the maximum.
def FindMax(root):
# ???
if (root == None):
return float('-inf')
# In this function, it will search for the maximum of three values, the roots, and maximums from left and right leaves.
# Initialization of 3 things: the maximum of root, and two maximums of left and right leaves
letsfind = root.data
lfound = FindMax(root.left)
rfound = FindMax(root.right)
# If a maximum is found on the left, new maximum is the value.
if(lfound > letsfind):
letsfind = lfound
# If a maximum is found on the right, new maximum is the value.
if(rfound > letsfind):
letsfind = rfound
# Return the maximum value found.
return letsfind
???
if name == 'main':
# The Inputs of the Binary Tree and leaves.
# root (Top most), root.left (Left Leaf), root.right (Right Leaf)
root = Node(2)
root.left = Node(7)
root.right = Node(5)
root.left.right = Node(6)
root.left.right.left= Node(1)
root.left.right.right= Node(11)
root.right.right= Node(9)
root.right.right.left= Node(4)
# Print the Maximum
print("The Maximum Value in the Binary Tree is: ", FindMax(root))
I know it seems long, so I apologize.
I have taken account that the function 'FindMax' needs to be outside of the class, in order for it to run properly.
One more thing though, what is the purpose of the statement if __name__ == '__main__':?
And What is the if (root == None): return float('-inf') Really for?
Thanks a lot guys. I appreciate it! :)

lis = FindMax(start.left)
ris = FindMax(start.right)
You forgot to call the recursive search

Option 1
The problem is here
st = start.data
lis = start.left
ris = start.right
while you actually call for the data node on st. The other ones (lis and ris) are only been call as Nodes. You should change it with
st = start.data
lis = (start.left).data
ris = (start.right).data
to be reading the data from all nodes
Option 2
You override > for your node class.
Funny but a not for a rookie. If you are interested start reading this

This is the correct code:
def findMax(start):
# Base case
if start is None:
return float('-inf')
st = start.data
lis = findMax(start.left)
ris = findMax(start.right)
if (lis > st):
st = lis
if (ris > st):
st = ris
return st
and call findMax() now
Tree=BinaryTree("1")
Tree.root.left=Node("2")
Tree.root.right=Node("3")
Tree.root.left.left=Node("4")
Tree.root.left.right=Node("5")
Tree.root.right.left=Node("6")
Tree.root.right.right=Node("7")
Tree.root.right.right.right=Node("8")
print("Maximum element is", findMax(start))

def findMax(root):
if (root == None):
return float('-inf')
res = root.data
lres = findMax(root.left)
rres = findMax(root.right)
if (lres > res):
res = lres
if (rres > res):
res = rres
return res
if __name__ == '__main__':
root = newNode(2)
root.left = newNode(7)
root.right = newNode(5)
root.left.right = newNode(6)
root.left.right.left = newNode(1)
root.left.right.right = newNode(11)
root.right.right = newNode(9)
root.right.right.left = newNode(4)
print("Maximum element is", findMax(root))
#Output
Maximum element is 11

Note - There are a few exceptions to my answer:
It may contain errors as OP did not provide the BinaryTree class.
Does not take into account any logical issues.
It is focused on getting OP's code working.
Here are the errors that I spotted:
Python is a language which requires proper indentation. Indentation is vital in-order for code to function properly. It appears that the way you have indented your code is incorrect.
When you are trying to call a function inside a class, you would need to make the call either via an instance (self) or the class itself (classmethods). Explanation provided here.
Explanation of if __name__ == "__main__": here. It is not really required as I assume your code is a single module (in one Python file) but is good to have when working with multiple modules.
Based on the points I have mentioned, I have corrected your code accordingly as follows:
# Any required imports goes here...
# import XXX
class BinaryTree:
# OP did not provide code sample...
class Node:
def __init__(self, data):
# Creating a node
self.data = data
# Pointing either left or right, but it is empty in default
self.left = None
self.right = None
def fmax(self, start):
if start is None:
return 0
st = start.data
lis = self.fmax(start.left)
ris = self.fmax(start.right)
if (lis > st):
st = lis
if (ris > st):
st = ris
return st
if __name__ == "__main__":
Tree = BinaryTree("1")
Tree.root.left = Node("2")
Tree.root.right = Node("3")
Tree.root.left.left = Node("4")
Tree.root.left.right = Node("5")
Tree.root.right.left = Node("6")
Tree.root.right.right = Node("7")
Tree.root.right.right.right = Node("8")
print(Tree.fmax(Tree.root))
If anyone spots any error with my code please feel free to edit it. My idea is to get OP a working code and he can expand from there.

Related

LeetCode expects null instead of None. How to do this in python?

I'm currently working on LeetCode problem 108. Convert Sorted Array to Binary Search Tree:
Given an integer array nums where the elements are sorted in ascending order, convert it to a height-balanced binary search tree.
A height-balanced binary tree is a binary tree in which the depth of the two subtrees of every node never differs by more than one.
My code seems to be working fine but I don't know how to display the value null instead of None in my list. I need to print the BST in level order traversal. I'm looking for advice, hints or suggestions.
Input:
[-10,-3,0,5,9]
My current output:
[0, -3, 9, -10, None, 5, None]
Accepted output:
[0,-3,9,-10,null,5]
Here is my code:
from queue import Queue
from typing import Optional
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def sortedArrayToBST(nums: [int]) -> Optional[TreeNode]:
nbNodes = len(nums)
if nbNodes == 1:
root = TreeNode()
root.val = nums[0]
return root
elif nbNodes == 0:
root = TreeNode()
root.val = None
return root
middle = int(nbNodes / 2)
root = TreeNode()
root.val = nums[middle]
leftList = []
rightList = []
j = middle + 1
for i in range(middle):
leftList.append(nums[i])
if j != nbNodes:
rightList.append(nums[j])
j += 1
root.left = sortedArrayToBST(leftList)
root.right = sortedArrayToBST(rightList)
return root
def levelorder(root):
if root==None:
return
Q=Queue()
Q.put(root)
level_order_list = []
while(not Q.empty()):
node=Q.get()
if node==None:
continue
level_order_list.append(node.val)
Q.put(node.left)
Q.put(node.right)
print(level_order_list)
if __name__ == "__main__":
container = [-10,-3,0,5,9]
levelorder(sortedArrayToBST(container))
This is kind of a weird requirement that has nothing to do with the apparent main point of the problem and I suspect it's a result of the description being copied over from one that's aimed at another language (like Javascript, which uses null instead of None).
You can, however, format your list however you like when you print it; here's an example where we print a list by joining each item with "," (instead of the default ", ") and replace None with "null":
>>> my_list = [0, -3, 9, -10, None, 5, None]
>>> print("[" + ",".join("null" if i is None else str(i) for i in my_list) + "]")
[0,-3,9,-10,null,5,null]
Since JSON renders None as null, another option would be to dump the list to JSON and remove the " " characters:
>>> import json
>>> print(json.dumps(my_list).replace(' ', ''))
[0,-3,9,-10,null,5,null]
The problem is not related to null or None. LeetCode is a platform for taking code challenges in many different languages and they use JSON style to describe input/output, and in JSON notation None translates to null.
Not to worry about that. However, when you look at your output, there is a trailing None that should not be there. That means that you returned a BST that has a node with a None value. This should not happen.
The code that creates this None valued node is easy to identify... it is here:
elif nbNodes == 0:
root = TreeNode()
root.val = None
return root
return
When you think of it, this cannot be right: the number of nodes to generate (nbNodes) is 0, yet your code creates 1 node -- and that is one too many! In this case you should just return None to indicate that the parent node has no child here.
So replace with:
elif nbNodes == 0:
return
This fixes the issue you mentioned, and your code will now pass all tests on LeetCode.
Here is your code with the above corrections and with the self parameter restored (which you had removed to run it without the need to create a class instance):
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
nbNodes = len(nums)
if nbNodes == 1:
root = TreeNode()
root.val = nums[0]
return root
elif nbNodes == 0:
return
middle = int(nbNodes / 2)
root = TreeNode()
root.val = nums[middle]
leftList = []
rightList = []
j = middle + 1
for i in range(middle):
leftList.append(nums[i])
if j != nbNodes:
rightList.append(nums[j])
j += 1
root.left = self.sortedArrayToBST(leftList)
root.right = self.sortedArrayToBST(rightList)
return root
Other improvements
Unrelated to your question, but there are several things you can optimise:
Try to avoid creating new lists (leftList, rightList): copying values into them takes time and space. Instead use start/end indices in the original list to denote which sublist is currently processed.
Make use of the additional arguments you can pass to the TreeNode constructor. That way you don't have to assign to attributes after the constructor has run.
Use the integer division operator instead of the floating point division operator.
One of the two base cases is not needed as it would be dealt with correctly by the next recursive calls.
Here is a spoiler solution that applies those remarks:
class Solution:
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
def recur(start: int, end: int):
if start < end:
middle = (start + end) // 2
return TreeNode(nums[middle],
recur(start, middle),
recur(middle + 1, end))
return recur(0, len(nums))

Need help understanding Python recursion issue for 103. Binary Tree Zigzag Level Order Traversal

While solving Leetcode problem '103. Binary Tree Zigzag Level Order Traversal', I ran into issue that I am unable to understand why.
Following is the serialize logic I am using -
def serialize(self, root):
if not root:
return 'n'
left = self.serialize(root.left)
right = self.serialize(root.right)
s = str(root.val)+','+left+','+right
return s
To deserialize, I am checking the first character to take action and function is called recursively for rest of elements.
def deserialize(self, data):
data = data.split(',') # serialized string is comma separated with 'n' for Null
def buildTree(data):
if not data:
return None
if data[0] == 'n':
data = data[1:] # 0 index element is used. Use rest next time onwards
return None
root = TreeNode(int(data[0]))
data = data[1:] # 0 index element is used. Use rest next time onwards
root.left = buildTree(data)
root.right = buildTree(data)
return root
return buildTree(data)
However, this is not working. But following code with same logic is working. Just the change is I am popping the first element and not reassigning.
Difference in Above : data = data[1:] and Below code : data.pop(0)
def deserialize(self, data):
data = data.split(',')
def buildTree(data):
if not data:
return None
c = data.pop(0)
if c == 'n':
return None
root = TreeNode(int(c))
root.left = buildTree(data)
root.right = buildTree(data)
return root
return buildTree(data)
Can you help me understand what might be the issue here? As the list is mutable, it should work. Thanks

Having issues trying to convert a binary search tree into a balanced search tree with just one method in python

class Node:
def __init__(self, data, left_child=None, right_child=None):
self.data = data
self.left_child = left_child
self.right_child = right_child
self.height = -1
class BinarySearchTree:
def __init__(self):
self.root = None
self.height = -1
self.balance = 0
def inorder(self):
return self.inorder_helper(self.root)
def inorder_helper(self, cur_node):
lyst = []
if cur_node is not None:
lyst += self.inorder_helper(cur_node.left_child)
lyst.append(str(cur_node.data))
lyst += self.inorder_helper(cur_node.right_child)
final_lyst = list(map(int, lyst))
return final_lyst
def rebalance_tree(self):
arr = self.inorder()
return self.rebalance_tree_helper(arr)
def rebalance_tree_helper(self, arr):
if not arr:
return None
mid = (len(arr)) // 2
root = Node(arr[mid])
root.left_child = self.rebalance_tree_helper(arr[:root])
root.right_child = self.rebalance_tree_helper(arr[root + 1:])
return root
bst.add(5)
bst.add(10)
bst.add(12)
bst.add(20)
bst.rebalance_tree()
print(bst)
Having issues trying to convert a binary search tree into a balanced search tree. So i currently have a binary search tree and it works correctly, 100%. However, I am trying to add a method that will balance the tree (aka turn it into an avl tree).
So i tried using https://www.geeksforgeeks.org/sorted-array-to-balanced-bst/ and tried making it a method into a tree, but i am having a few issues.
it keeps saying that i am reaching the recursion limit, and this is worrying me as i added these few lines of code that makes the recursion limit a lot higher then it should be needed:
resource.setrlimit(resource.RLIMIT_STACK, (2**29,-1))
sys.setrecursionlimit(10**6)
So now I am wondering if my method is running infinitely and causing the recursion limit, but i took a long look at the rebalance_helper and it looks like its not infinite.
If anyone can give me any insight i would really appreciate it. Thank you!

Implementing Binary Search Tree (Python)

I have the task to perform some basic operations on Binary Search Trees and I'm not sure what is the clever way to do it.
I know that the usual way would be to write a class for the nodes and one for the tree so that I can build up my tree from given values and perform certain tasks on it. The thing is, I'm already getting the tree as a list and since BSTs are not unique, there won't come any good from it if I take each value and build the tree myself.
So... I'm getting a list like this:
11 9 2 13 _, 4 18 2 14 _, 2 10 _ 11 4, 14 16 4 _ _, 13 0 11 _ _ | 10 | 7
which means:
key value parent left right, ... | value1 | value2
So as you see the BST is given explicitly. My tasks are to do a level-print of the tree, return the path from root to value1, do a rotate-right operation on the subtree that has value1, then delete value1 and then insert value2.
What would be an efficient way to tackle this problem?
Here is one possible way of implementing the tree. Hope it helps. Though this contains insertions and popular traversals, not rotations or deletions.
Reference: http://www.thelearningpoint.net/computer-science/learning-python-programming-and-data-structures/learning-python-programming-and-data-structures--tutorial-20--graphs-breadth-and-depth-first-search-bfsdfs-dijkstra-algorithm-topological-search
'''
Binary Search Tree is a binary tree(that is every node has two branches),
in which the values contained in the left subtree is always less than the
root of that subtree, and the values contained in the right subtree is
always greater than the value of the root of the right subtree.
For more information about binary search trees, refer to :
http://en.wikipedia.org/wiki/Binary_search_tree
'''
#Only for use in Python 2.6.0a2 and later
from __future__ import print_function
class Node:
# Constructor to initialize data
# If data is not given by user,its taken as None
def __init__(self, data=None, left=None, right=None):
self.data = data
self.left = left
self.right = right
# __str__ returns string equivalent of Object
def __str__(self):
return "Node[Data = %s]" % (self.data,)
class BinarySearchTree:
def __init__(self):
self.root = None
'''
While inserting values in a binary search tree, we first check
whether the value is greater than, lesser than or equal to the
root of the tree.
We initialize current node as the root.
If the value is greater than the current node value, then we know that
its right location will be in the right subtree. So we make the current
element as the right node.
If the value is lesser than the current node value, then we know that
its right location will be in the left subtree. So we make the current
element as the left node.
If the value is equal to the current node value, then we know that the
value is already contained in the tree and doesn't need to be reinserted.
So we break from the loop.
'''
def insert(self, val):
if (self.root == None):
self.root = Node(val)
else:
current = self.root
while 1:
if (current.data > val):
if (current.left == None):
current.left = Node(val)
break
else:
current = current.left
elif (current.data < val):
if (current.right == None):
current.right = Node(val)
break
else:
current = current.right
else:
break
'''
In preorder traversal, we first print the current element, then
move on to the left subtree and finally to the right subree.
'''
def preorder(self, node):
if (node == None):
return
else:
print(node.data, end=" ")
self.preorder(node.left)
self.preorder(node.right)
'''
In inorder traversal, we first move to the left subtree, then print
the current element and finally move to the right subtree.
'''
#Important : Inorder traversal returns the elements in sorted form.
def inorder(self, node):
if (node == None):
return
else:
self.inorder(node.left)
print(node.data, end=" ")
self.inorder(node.right)
'''
In postorder traversal, we first move to the left subtree, then to the
right subtree and finally print the current element.
'''
def postorder(self, node):
if (node == None):
return
else:
self.postorder(node.left)
self.postorder(node.right)
print(node.data, end=" ")
tree = BinarySearchTree()
tree.insert(1)
tree.insert(9)
tree.insert(4)
tree.insert(3)
tree.insert(5)
tree.insert(7)
tree.insert(10)
tree.insert(0)
print ("Preorder Printing")
tree.preorder(tree.root)
print("\n\nInorder Printing")
tree.inorder(tree.root)
print("\n\nPostOrder Printing")
tree.postorder(tree.root)
Here is the implementation of Binary Search Tree with it's basic operations like insert node, find node
class Node:
def __init__(self,data):
self.left = None
self.right = None
self.data = data
class BST:
def __init__(self):
self.root = None
def set_root(self,data):
self.root = Node(data)
def insert_node(self,data):
if self.root is None:
self.set_root(data)
else:
n = Node(data)
troot = self.root
while troot:
if data < troot.data:
if troot.left:
troot = troot.left
else:
troot.left = n
break
else:
if troot.right:
troot = troot.right
else:
troot.right = n
break
def search_node(self,data):
if self.root is None:
return "Not found"
else:
troot = self.root
while troot:
if data < troot.data:
if troot.left:
troot = troot.left
if troot.data == data:
return "Found"
else:
return "Not found"
elif data > troot.data:
if troot.right:
troot = troot.right
if troot.data == data:
return "Found"
else:
return "Not found"
else:
return "Found"
tree = BST()
tree.insert_node(10)
tree.insert_node(5)
tree.insert_node(20)
tree.insert_node(7)
print(tree.root.data)
print(tree.root.left.data)
print(tree.root.right.data)
print(tree.root.left.right.data)
print(tree.search_node(10))
print(tree.search_node(5))
print(tree.search_node(20))
print(tree.search_node(7))
print(tree.search_node(12))
print(tree.search_node(15))
Output:
10
5
20
7
Found
Found
Found
Found
Not found
Not found
In this specific case I had success using a dictionary as a datatype to store the graph. The key is the node_key and the value is a list with the attributes of the node. In this way it is rather fast to find the needed nodes and all its attributes.
I'm just not sure if there is a way to make it reasonably faster.

Print a binary tree, python, in inorder

Me and my friend are doing some school work with programming in Python 3.1 and are VERY stuck. We're programming a binary tree and it's working fine except when we want to print all the nodes in inorder in a way that would create a sentence (all the words in inorder just after one another in a row). We have been looking all over the internet for clues as to how to procede and we've been working with this little thing for like two hours. Any advice/help would be awesome.
Our program/Binary tree:
class Treenode:
def __init__(self, it = None, le = None, ri = None):
self.item = it
self.left = le
self.right = ri
class Bintree:
def __init__(self):
self.item = None
self.left = None
self.right = None
def put(self, it = None):
key = Treenode(it)
if self.item == None:
self.item = key
return
p = self.item
while True:
if key.item < p.item:
if p.left == None:
p.left = key
return
else:
p = p.left
elif key.item > p.item:
if p.right == None:
p.right = key
return
else:
p = p.right
else:
return
def exists(self, it):
key = it
p = self.item
if p == key:
return True
while True:
if key < p.item:
if p.left == None:
return False
else:
p = p.left
elif key > p.item:
if p.right == None:
return False
else:
p = p.right
else:
return
def isEmpty(self):
if self.item == None:
return True
else:
return False
def printtree (Treenode):
if Treenode.left != None:
printtree (Treenode.left)
print (Treenode.item)
if Treenode.right != None:
printtree (Treenode.right)
We get a sort of print when we run the program which looks like this: "bintree.Treenode object at 0x02774CB0", which is not what we want.
We use the tree by running this:
import bintree
tree = bintree.Bintree()
print(tree.isEmpty()) # should give True
tree.put("solen")
print(tree.isEmpty()) # should give False
tree.put("gott")
tree.put("sin")
tree.put("hela")
tree.put("ban")
tree.put("upp")
tree.put("himlarunden")
tree.put("manen")
tree.put("seglar")
tree.put("som")
tree.put("en")
tree.put("svan")
tree.put("uti")
tree.put("midnattsstuden")
print(tree.exists("visa")) # should give False
print(tree.exists("ban")) # should give True
tree.printtree() # print sorted
Also, the second last row gives us "None" instead of "True", which is wierd.
To print a binary tree, if you are printing a leaf you just print the value; otherwise, you print the left child then the right child.
def print_tree(tree):
if tree:
print tree.value
print_tree(tree.left)
print_tree(tree.right)
print(tree.exists("visa")) returns None, because in the last line of exists() there's return statement without any value (which defaults to None).
Also you shouldn't name a printtree argument Treenode since it's a name of an existing class and that might lead to confusion. It should look more like:
def printtree(tree_node):
if tree_node.left is not None:
printtree(tree_node.left)
print(tree_node.item)
if tree_node.right is not None:
printtree(tree_node.right)
Another thing is calling printtree - it's a function, not Bintree method, so I suppose you should call it printtree(tree).
One way to make testing easier is to use -assert()- instead of printing things and then referring back to your code.
tree = Bintree()
assert(tree.isEmpty())
tree.put("solen")
assert(not tree.isEmpty())
tree.put("gott")
tree.put("sin")
tree.put("hela")
tree.put("ban")
http://docs.python.org/reference/simple_stmts.html#the-assert-statement
It raises an error if its condition is not true. I know that doesn't fix your bug but making things less ambiguous always helps debugging.
You are not specifying a starting case for printtree(). You're defining how to recurse through your tree correctly, but your call to printtree() has no node to start at. Try setting a default check to see if a parameter is passed in, and if one isn't start at the head node of the bintree.
The reason your second to last line is printing None is because, in your exists method, you just have a "return", rather than a "return True", for the case of finding a `p.item' that is equal to key.

Categories