Create an empty Binary Tree in Python - python-3.x

I'm a beginner in programming, and I couldn't find the answer in other questions.
I'd like to create an empty binary tree of height h.
My code:
class node:
def __init__(self, a = None):
self.value = a
self.left = None
self.right = None
def postorder(tree,abba):
if tree != None:
postorder(tree.left,abba)
postorder(tree.right,abba)
abba.append(tree.value)
def inorder(tree,abba):
if tree != None:
inorder(tree.left,abba)
abba.append(tree.value)
inorder(tree.right,abba)
I would like to define a function
def getBinaryTree(h):
That gives me a tree with level h. So:
empty tree of level
Any ideas?

Updated
To make a binary tree with height h, you need to add 2^(h+1)-1 nodes. A tree with height 0 means, the tree contains only one node and that is the root. For example, to create a tree with height 3, you need to add 2^(3+1)-1 = 15 nodes.
If you want to create a set of nodes which can form a binary tree with your given code, you can do something like this.
import math
class node:
def __init__(self, a = None):
self.value = a
self.left = None
self.right = None
def getBinaryTree(tree_height):
tree_nodes = [None] * int((math.pow(2, tree_height+1) - 1))
for i in range(tree_height):
start_index = int(math.pow(2, i) - 1)
end_index = int(math.pow(2, i+1) - 1)
for j in range(start_index, end_index):
tree_nodes[j] = node(j)
if j == 0: continue
if j % 2 == 0: # a right child
parent_index = int((j - 2) / 2)
tree_nodes[parent_index].right = tree_nodes[j]
else: # a left child
parent_index = int((j - 1) / 2)
tree_nodes[parent_index].left = tree_nodes[j]
return tree_nodes[0] # returns the root node
def printTree(tree_node, inorder_tree_walk):
if tree_node != None:
printTree(tree_node.left, print_tree)
inorder_tree_walk.append(tree_node.value)
printTree(tree_node.right, print_tree)
root = getBinaryTree(4)
inorder_tree_walk = []
printTree(root, inorder_tree_walk)
print(inorder_tree_walk)
So, what the program does?
The program creates 2^(h+1)-1 nodes to form a tree with height h. Nodes are stored in list tree_nodes. Parent-child relationship between nodes are stored in tree_nodes as follows.
Left child of element i: (2i + 1)th element
Right child of element i: (2i + 2)th element
When a children node is created, it is set as a left/right children of its parent.

Related

Is there a way to nest a recursive function that updates a list with outer enclosing scope?

I'm trying to solve the following problem.
Given the root of a binary tree, construct a 0-indexed m x n string matrix res that represents a formatted layout of the tree. The formatted layout matrix should be constructed using the following rules:
The height of the tree is height and the number of rows m should be equal to height + 1.
The number of columns n should be equal to 2**(height+1) - 1.
Place the root node in the middle of the top row (more formally, at location res[0][(n-1)/2]).
For each node that has been placed in the matrix at position res[r][c], place its left child at res[r+1][c-2height-r-1] and its right child at res[r+1][c+2**(height-r-1)].
Continue this process until all the nodes in the tree have been placed.
Any empty cells should contain the empty string "".
Return the constructed matrix res.
This is my code:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
def find_h(node: Optional[TreeNode]) -> int:
if not node:
return 0
return 1 + max(find_h(node.left), find_h(node.right))
class Solution:
def printTree(self, root: Optional[TreeNode]) -> List[List[str]]:
height = find_h(root)
res = [['' for _ in range(2 ** height - 1)] for _ in range(height)]
def dispNode(node: Optional[TreeNode], r: int, c: int):
res[r][c] = str(node.val)
if node.left:
dispNode(node.left, r + 1, c - 2**(height-r-2))
if node.right:
dispNode(node.right, r + 1, c + 2**(height-r+2))
dispNode(root, 0, 2**(height - 1) - 1)
return res
I get an index out of bounds error and if I use a try-except block on the res[r][c] = str(node.val) line, I still only get the left nodes only. Is there something wrong with the way variable scopes are working?

How to get return values of one class and put it into another class on a different file?

So I have this one method that is part of a class? It is part of another class above it.
Right here:
def bfs(self, v):
searchOrders = []
parent = len(self.vertices) * [-1] # Initialize parent[i] to -1
queue = Queue() # the Queue class is defined in Chapter 17
isVisited = len(self.vertices) * [False]
queue.enqueue(v) # Enqueue v
isVisited[v] = True # Mark it visited
while not queue.isEmpty():
u = queue.dequeue() # Dequeue to u
searchOrders.append(u) # u searched
for e in self.neighbors[u]:
if not isVisited[e.v]:
queue.enqueue(e.v) # Enqueue w
parent[e.v] = u # The parent of w is u
isVisited[e.v] = True # Mark it visited
I want the return values of this
return Tree(v, parent, searchOrders, self.vertices)
To be able to use this other class
class Tree:
def __init__(self, root, parent, searchOrders, vertices):
self.root = root # The root of the tree
# Store the parent of each vertex in a list
self.parent = parent
# Store the search order in a list
self.searchOrders = searchOrders
self.vertices = vertices # vertices of the graph
#I want this method
# Return the path of vertices from a vertex index to the root
def getPath(self, index):
path = []
while index != -1:
path.append(self.vertices[index])
index = self.parent[index]
return path
I do not know how to put it in this so far I have it like this
# Call the method (bfs) to set a path (if connected) between input vertices
#####################################################
n.bfs(integer_indexes[0])
#####################################################
s = Tree(n.bfs(integer_indexes[0]))
s.getPath[1]
# Print the path that connect two input vertices
#####################################################
print("Shortest path is:", s)
#####################################################
As a result I should get the return values of bf method and put it into Tree class so I can call the getPath method, and then print accordingly

Test Leetcode 104. Maximum Depth of Binary Tree

I am testing the leetcode 104 Maximum Depth of Binary Tree. While testing the case root = [3,9,20,None, None,15,7] . The output should be 3 but it shows 2. Could someone help me with this. Thanks
class TreeNode:
def __init__(self,val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def createTreeNode(nodeList):
root = TreeNode(nodeList[0])
root.left = TreeNode(nodeList[1])
root.right = TreeNode(nodeList[2])
return root
def maxDepth(root):
if root is None:
return 0
else:
max_left = maxDepth(root.left)
max_right = maxDepth(root.right)
return max(max_left, max_right) + 1
def main():
ListNode1 = [3,9,20,None,None,15,7]
TreeNode1 = createTreeNode(ListNode1)
print (maxDepth(TreeNode1))
main()
You do not construct your tree in the right way. Leetcode recently added an option to visualize trees (see Tree Visualizer in the right-bottom corner of the Testcase tab). For your input:
In test cases usually trees are represented as in-order traversal, so you can build up a tree from it using suitable traversal algorithm or you could build it manually:
root = TreeNode(3)
root.left = TreeNode(9)
root.right = TreeNode(20)
root.right.right = TreeNode(7)
root.right.left = TreeNode(15)
Your algorithm is correct, but I would refactor it a bit:
def maxDepth(root):
if not root:
return 0
max_left = maxDepth(root.left)
max_right = maxDepth(root.right)
return max(max_left, max_right) + 1

Nodes at given distance in binary tree (Amazon SDE-2)

Given a binary tree, a target node in the binary tree, and an integer value k, find all the nodes that are at distance k from the given target node. No parent pointers are available.
link to the problem on GFG: LINK
Example 1:
Input :
20
/ \
8 22
/ \
4 12
/ \
10 14
Target Node = 8
K = 2
Output: 10 14 22
Explanation: The three nodes at distance 2
from node 8 are 10, 14, 22.
My code
from collections import defaultdict
class solver:
def __init__(self):
self.vertList = defaultdict(list)
def addEdge(self,u,v):
self.vertList[u].append(v)
def makeGraph(self,root):
visited = set()
queue = []
queue.append(root)
while len(queue) > 0:
curr = queue.pop(0)
visited.add(curr)
if curr.left is not None and curr.left not in visited:
self.vertList[curr.data].append(curr.left.data)
self.vertList[curr.left.data].append(curr.data)
queue.append(curr.left)
if curr.right is not None and curr.right not in visited:
self.vertList[curr.data].append(curr.right.data)
self.vertList[curr.right.data].append(curr.data)
queue.append(curr.right)
def KDistanceNodes(self,root,target,k):
self.makeGraph(root)
dist = {}
for v in self.vertList:
dist[v] = 0
visited2 = set()
queue2 = []
queue2.append(target)
while len(queue2) > 0:
curr = queue2.pop(0)
visited2.add(curr)
for nbr in self.vertList[curr]:
if nbr not in visited2:
visited2.add(nbr)
queue2.append(nbr)
dist[nbr] = dist[curr] + 1
ans = []
for v in dist:
if dist[v] == k:
ans.append(str(v))
return ans
#{
# Driver Code Starts
#Initial Template for Python 3
from collections import deque
# Tree Node
class Node:
def __init__(self, val):
self.right = None
self.data = val
self.left = None
# Function to Build Tree
def buildTree(s):
# Corner Case
if (len(s) == 0 or s[0] == "N"):
return None
# Creating list of strings from input
# string after spliting by space
ip = list(map(str, s.split()))
# Create the root of the tree
root = Node(int(ip[0]))
size = 0
q = deque()
# Push the root to the queue
q.append(root)
size = size + 1
# Starting from the second element
i = 1
while (size > 0 and i < len(ip)):
# Get and remove the front of the queue
currNode = q[0]
q.popleft()
size = size - 1
# Get the current node's value from the string
currVal = ip[i]
# If the left child is not null
if (currVal != "N"):
# Create the left child for the current node
currNode.left = Node(int(currVal))
# Push it to the queue
q.append(currNode.left)
size = size + 1
# For the right child
i = i + 1
if (i >= len(ip)):
break
currVal = ip[i]
# If the right child is not null
if (currVal != "N"):
# Create the right child for the current node
currNode.right = Node(int(currVal))
# Push it to the queue
q.append(currNode.right)
size = size + 1
i = i + 1
return root
if __name__ == "__main__":
x = solver()
t = int(input())
for _ in range(t):
line = input()
target=int(input())
k=int(input())
root = buildTree(line)
res = x.KDistanceNodes(root,target,k)
for i in res:
print(i, end=' ')
print()
Input:
1 N 2 N 3 N 4 5
target = 5
k = 4
Its Correct output is:
1
And Your Code's output is:
[]
My logic:
-> First convert the tree into a undirected graph using BFS / level order traversal
-> Traverse the graph using BFS and calculate the distance
-> Return the nodes at k distance from the target
What I think:
First of all in the given test case the tree representation seems to be in level order however, in the failing test case it doesn't look like level order or maybe my logic is wrong?
Input Format:
Custom input should have 3 lines. First line contains a string representing the tree as described below. Second line contains the data value of the target node. Third line contains the value of K.
The values in the string are in the order of level order traversal of the tree where, numbers denote node values, and a character ā€œNā€ denotes NULL child.
For the above tree, the string will be: 1 2 3 N N 4 6 N 5 N N 7 N
The mistake is that the logic that is done in "init" should be done for every use-case (reinitializing self.vertList), not just once at the beginning.
Change:
def __init__(self):
self.vertList = defaultdict(list)
to:
def __init__(self):
pass
and:
def KDistanceNodes(self,root,target,k):
self.makeGraph(root)
dist = {}
...
to:
def KDistanceNodes(self, root, target, k):
self.vertList = defaultdict(list) # <-- move it here
self.makeGraph(root)
dist = {}
...
The original code kept accumulating the nodes and "remembered" the previous use-cases.
Also pay attention that you should return ans sorted, meaning that you should not append the numbers as strings so that you'll be able to sort them, change: ans.append(str(v)) to: ans.append(v) and return sorted(ans).

Finding the sum of leaves in a Binary tree using nodes

I want to be able to recursively find the sum of all the leaves in a binary tree through the use of nodes so far I have:
class BTNode:
"""A node in a binary tree."""
def __init__(self: 'BTNode', item: object,
left: 'BTNode' =None, right: 'BTNode' =None) -> None:
"""Initialize this node.
"""
self.item, self.left, self.right = item, left, right
def __repr__(self):
return 'BTNode({}, {}, {})'.format(repr(self.item),
repr(self.left), repr(self.right))
def is_leaf(self: 'BTNode') -> bool:
return not self.left and not self.right
def tree_sum(t: BTNode) -> int:
'''Return the sum of the leaves in t.
>>> t = BTNode(None, BTNode(8), BTNode(9))
>>> tree_sum(t)
17
'''
sm = 0
t1 = t.left.item
t2 = t.right.item
if not t.left or not t.right:
return 0
if t.left.is_leaf() and t.right.is_leaf():
sm = t1 + t2 + tree_sum(t.left) + tree_sum(t.right)
return sm
The function tree_sum(t) I have doesn't work, I'm struggling to find a way that works. What am i doing incorrectly?
You are missing a tiny bit of code.
Since t.left and t.right will be None if t is a leaf, the lines t1 = t.left.item and t2 = t.right.item will raise an AttributeError.
You need to take that into account:
t1 = t.left.item if t.left else None
t2 = t.right.item if t.right else None
Then
t = BTNode(None, BTNode(8), BTNode(9))
print(tree_sum(t))
produces the correct result (17).
That said, this function will not return the sum of all leaves (ie it won't traverse the whole tree in case of a multi-level tree).

Resources