class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
def printPaths(root):
path = []
printPathsRec(root, path, 0)
def printPathsRec(root, path, pathLen):
if root is None:
return
if(len(path) > pathLen):
path[pathLen] = root.data
else:
path.append(root.data)
pathLen = pathLen + 1
if root.left is None and root.right is None:
printArray(path, pathLen)
else:
printPathsRec(root.left, path, pathLen)
printPathsRec(root.right, path, pathLen)
def printArray(ints, len):
for i in ints[0 : len]:
print(i," ",end="")
print()
from binarytree import build
values = [7, 3, 2, 6, 9, None, 1, 5, 8]
root = build(values)
print(root)
printPaths(root.value)
.
I need to build binary tree with build and make the code work, but i can't find out the way.
This example is get from internet,they use method like
root = Node(10)
root.left = Node(8)
root.right = Node(2)
root.left.left = Node(3)
root.left.right = Node(5)
root.right.left = Node(2)
printPaths(root)
But i need to use another method to make it happen.
I am going to guess that values contains the level-order values of the tree, where the children below a None are not included (instead of having two filler None values).
Then the algorithm to populate a new tree will also follow a level-order way of populating. For this you typically use a queue or deque or two lists. For example:
def build(values):
if not values:
return
it = iter(values)
root = Node(next(it))
level = [root]
while level:
nextlevel = []
for parent in level:
value = next(it, None)
if value is not None:
parent.left = Node(value)
nextlevel.append(parent.left)
value = next(it, None)
if value is not None:
parent.right = Node(value)
nextlevel.append(parent.right)
level = nextlevel
return root
To create binary Tree:
you need a list sequential.
class Node:
count = 0
def __init__(self, val):
self.left = None
self.right = None
self.val = val
Node.count+= 1
def __str__(self):
return (f"value is {self.val} \ncount is:{self.count}")
If info is given as:
from collections import deque
d = {0:[1,2], 2:[4,5], 1:[3]} # how nodes are connected. key is node number and values is node num of children.
vals = [10,11,12,13,14,15] # values associated with the node num
q = deque()
q.append(0) #<---- root node
li = [vals[0]] #<--- root node val
while(len(q)>0):
front = q.popleft()
if (d.get(front, 0)):
if(len(d[front])==2):
li.append(vals[d[front][0]])
li.append(vals[d[front][1]])
q.append(d[front][0])
q.append(d[front][1])
else:
li.append(vals[d[front][0]])
li.append(None)
q.append(d[front][0])
# q.append(d[front][1])
else:
li.append(None)
li.append(None)
This will give you list
li:
[10, 11, 12, 13, None, 14, 15, None, None, None, None, None, None]
build:
def build(values):
if not values:
return None
it = iter(values)
root=Node(next(it))
q = deque()
q.append(root)
while(q):
front = q.popleft()
val1 = next(it, None)
if (val1):
n1 = Node(val1)
q.append(n1)
front.left = n1
val2 = next(it, None)
if (val2):
n2 = Node(val2)
q.append(n2)
front.right = n2
return root
node = build(li)
To print in inorder:
def print_node(root):
if not root:
return
print_node(root.left)
print(root.val, end=" ")
print_node(root.right)
print_node(node)
13 11 10 14 12 15
Straight Forward:
from collections import deque
d = {0:[1,2], 2:[4,5], 1:[3]}
vals = [10,11,12,13,14,15]
q = deque()
root = Node(vals[0], 0)
q.append(root)
while(q):
node = q.popleft()
if (d.get(node.node_num, {})):
if(len(d[node.node_num])==2):
no1 = d[node.node_num][0]
node.left = Node(vals[no1],no1)
no2 = d[node.node_num][1]
node.right = Node(vals[no2], no2)
q.append(node.left)
q.append(node.right)
else:
no1 = d[node.node_num][0]
node.left = Node(vals[no1],no1)
q.append(node.left)
print_node(root)
13 11 10 14 12 15
Added 1 attribute for node_num in class Node
Related
this is my code but im not being able to count the nodes in the list, ive also given the test cases below those test cases should get executed
class LinkedList:
def __init__(self, a):
self.head = None
tail=None
list=[]
for x in a:
if x not in list:
list+=[x]
if len(a)!=len(list):
print("all keys are not unique")
if len(a)==0:
print("Array is empty.")
else:
for x in a:
newNode = Node(x, None)
if (self.head == None):
self.head = newNode
tail = newNode
else:
tail.next = newNode
tail = newNode
# Count the number of nodes in the list
def countNode(self):
self.head= None
pass # Remove this line
test cases
print("////// Test 01 //////")
a1 = [10, 20, 30, 40]
h1 = LinkedList(a1) # Creates a linked list using the values from the array
# head will refer to the Node that contains the element from a[0]
h1.printList() # This should print: 10,20,30,40
print(h1.countNode()) # This should print: 4
I am assuming your Node looks like this
class Node:
def __init__(self, val, next_=None):
self.element = val
self.next = next_ # you should use next_
#property
def countNode(self):
temp = self.head
cnt = 0
while temp:
cnt += 1
temp = temp.next
def printList(self):
temp = self.head
while temp:
print(temp.element) # if Node contains val for value
temp = temp.next
Going along with your code,
h1 = LinkedList(a1)
# for count -> h1.countNode
# for print -> h1.printList()
I must implement a sum for each level in a binary tree
I must return a list that contains at position i, the ith sum
example: if I have this tree
24
/ \
14 27
/ \ / \
11 20 12 55
I must return [24, 41, 98]
I tried to implement this solution in python
def sommaperlivelli(p, lista):
if p == None:
return
if p.left != None and p.right != None:
lista.append(p.left.key + p.right.key)
sommaperlivelli(p.left, lista)
sommaperlivelli(p.right, lista)
return lista
I can get only the first sum and I can't add the root. How I can do it?
this is the class that I use
class NodoABR:
def __init__(self, key = None, left = None, right = None, parent = None):
self.key = key
self.left = left
self.right = right
self.parent = parent
this is how I add node to the tree
def inserisciNodo(p, n):
if p == None:
return NodoABR(n)
else:
if p.key == n:
return p
elif p.key < n:
rchild = inserisciNodo(p.right, n)
p.right = rchild
rchild.parent = p
else:
lchild = inserisciNodo(p.left, n)
p.left = lchild
lchild.parent = p
return p
this is a BinarySearchTree
in main function I do this
p = NodoABR(24)
p = inserisciNodo(p, 14)
p = inserisciNodo(p, 27)
p = inserisciNodo(p, 11)
p = inserisciNodo(p, 20)
p = inserisciNodo(p, 12)
p = inserisciNodo(p, 55)
print(sommaperlivelli(p,[]))
Assuming you have similar Tree Node class, you can try this & modify to suite your particular needs.
from collections import deque
class Node: # TreeNode eg.
def __init__(self, key):
self.data = key
self.left = None
self.right = None
def LevelSum(root):
answer = []
if (root == None): return 0 # base case
result = root.data
# track of # nodes at every level when traversal, and sum them up
q = deque()
q.append(root)
while len(q): # > 0):
size = len(q)
# Iterate for all the nodes
tot = 0
while size: # meaning --- size > 0
# Dequeue an node from queue
tmp = q.popleft()
# Add this node's value to current sum.
tot += tmp.data
# Enqueue left and right children of dequeued node
if (tmp.left != None): q.append(tmp.left)
if (tmp.right != None): q.append(tmp.right)
size -= 1
print(tot, result)
answer.append(tot)
return answer
Example:
if __name__ == '__main__':
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)
root.right.right = Node(6)
root.right.right.left = Node(9)
root.right.right.right = Node(11)
"""
# Constructed Binary tree is:
# 1
# / \
# 2 3 # 5
# / \ \
# 4 5 6 # 15
# / \
# 9 11 # 20
"""
print("level sum is", LevelSum(root))
[Edit] The PO author wants to learn another approach. (non-queue)
from collections import Counter
from typing import List
class Node:
def __init__(self, key):
self.data = key
self.left = None
self.right = None
def level_sum(root: Node) -> int:
def dfs(node, level):
if not node: return
total[level] += node.data
dfs(node.left,level + 1)
dfs(node.right,level + 1)
total = Counter()
dfs(root, 1)
print(total) # showing each level & its total --- can be commented out
return total.most_common()[0][1] # the largest total
Using your NodoABR class, here's a simple tree traversal, depth-first, where we note the level at each iteration, and use it to store the node values, arr is an array (or list) of lists, one for each level:
# Create sample tree
root = NodoABR(24, NodoABR(14, NodoABR(11), NodoABR(20)), NodoABR(27, NodoABR(12), NodoABR(55)))
def handle_node(nd, level):
# Add a new level list if needed
if len(arr) == level:
arr.append([])
# Append this node value to its proper level list
arr[level].append(nd.key)
# Recurse, increasing the level
if nd.left is not None:
handle_node(nd.left, level+1)
if nd.right is not None:
handle_node(nd.right, level+1)
# Main program
arr = []
handle_node(root, 0)
print(arr)
And this is the output:
[[24], [14, 27], [11, 20, 12, 55]]
I want to return a list of sorted order, provided I'm given a start/stop value for the method. For example, if start=2 and end=8, then i want to return a list within that range, implicitly, of the values in the BST in sorted order.
Since I want it to be in sorted order and not allowed to post sort the list after the method call, I think i should traverse the bst via in order traversal. when I test my implementation, first first doctest return [7,9,11] instead of [5,7,9,11] as intended.
from __future__ import annotations
from typing import Any, List, Optional, Tuple
class BinarySearchTree:
"""Binary Search Tree class.
# === Representation Invariants ===
# - If self._root is None, then so are self._left and self._right.
# This represents an empty BST.
# - If self._root is not None, then self._left and self._right
# are BinarySearchTrees.
# - (BST Property) If self is not empty, then
# all items in self._left are <= self._root, and
# all items in self._right are >= self._root.
"""
def __init__(self, root: Optional[Any]) -> None:
"""Initialize a new BST containing only the given root value.
If <root> is None, initialize an empty tree.
"""
if root is None:
self._root = None
self._left = None
self._right = None
else:
self._root = root
self._left = BinarySearchTree(None)
self._right = BinarySearchTree(None)
def is_empty(self) -> bool:
"""Return True if this BST is empty.
>>> bst = BinarySearchTree(None)
>>> bst.is_empty()
True
>>> bst = BinarySearchTree(10)
>>> bst.is_empty()
False
"""
return self._root is None
def items_in_range(self, start: Any, end: Any) -> List:
"""Return the items in this BST between <start> and <end>, inclusive.
Precondition: all items in this BST can be compared with <start> and
<end>.
The items should be returned in sorted order.
As usual, use the BST property to minimize the number of recursive
calls.
>>> bst = BinarySearchTree(7)
>>> left = BinarySearchTree(3)
>>> left._left = BinarySearchTree(2)
>>> left._right = BinarySearchTree(5)
>>> right = BinarySearchTree(11)
>>> right._left = BinarySearchTree(9)
>>> right._right = BinarySearchTree(13)
>>> bst._left = left
>>> bst._right = right
>>> bst.items_in_range(4, 11)
[5, 7, 9, 11]
>>> bst.items_in_range(10, 13)
[11, 13]
"""
if self.is_empty():
return []
else:
#use helper here
if end >= self._root >= start:
return (self._left._helper_items_in_range_left(start)
+ [self._root]
+ self._right._helper_item_in_range_right(end))
elif self._root > end:
return self._left.items_in_range(start,end)
elif self._root < start:
return self._right.items_in_range(start,end)
else:
pass
def _helper_items_in_range_left(self, start):
if self.is_empty():
return []
elif self._root < start:
return []
else:
return self._left._helper_items_in_range_left(start) +\
[self._root] + self._right._helper_items_in_range_left(start)
def _helper_item_in_range_right(self, end):
if self.is_empty():
return []
elif self._root > end:
return []
else:
return self._left._helper_item_in_range_right(end) + [self._root] +\
self._right._helper_item_in_range_right(end)
You could use something like this. Note that I tested it using a different tree structure.
import itertools
from collections import deque
class BSTIterator(object):
def __init__(self, root):
# Constructor takes in a tree root
self.stack = deque()
self._get_min(root)
def _get_min(self, root):
# We need to create our stack, i.e. dive down the left
curr = root
while curr != None:
self.stack.append(curr)
curr = curr.left
def __iter__(self): # Return self as the iterator
return self
def __next__(self): # Every time `next` is called return our data.
try:
curr = self.stack.pop()
self._get_min(curr.right)
return curr.data
except IndexError:
raise StopIteration
Tree type used:
class Node:
def __init__(self, data):
self.left = None
self.right = None
self.data = data
def insert(self, data):
if self.data:
if data < self.data:
if self.left is None:
self.left = Node(data)
else:
self.left.insert(data)
elif data > self.data:
if self.right is None:
self.right = Node(data)
else:
self.right.insert(data)
else:
self.data = data
Tested with:
root = Node(8)
root.insert(3)
root.insert(10)
root.insert(1)
root.insert(7)
root.insert(12)
root.insert(121)
root.insert(23)
root.insert(19)
root.insert(9)
b_iter = BSTIterator(root)
# root.print_tree()
# Since we now have an iterator we can for loop over it
# such as
# y = [x for x in b_iter]
# or we can slice it like
y = [x for x in itertools.islice(b_iter, 2, 5)]
print(y)
Prints:
[7, 8, 9]
That is how I would define a method returning a list of nodes from a given range (inclusive, non-decreasing order).
class Tree:
def __init__(self, root):
self.root = root
def nodes_in_range(self, start, end):
def search_range(node):
if node is not None:
if start <= node.value:
yield from search_range(node.left)
if start <= node.value <= end:
yield node.value
if end >= node.value:
yield from search_range(node.right)
return list(search_range(self.root))
I'm implementing a BST in Python but I have issues with but_insert(t, k).
Basically if I just add children to the root, like below, it works:
T = Node(7)
bst_insert(T, 9)
bst_insert(T, 5)
But if I insert another key, then an entire branch from the root seems to be dropped. For instance, if I execute:
T = Node(7)
bst_insert(T, 9)
bst_insert(T, 5)
bst_insert(T, 3)
Then when I print T in order I only get 7 9.
Here is the Node constructor and bst_insert (the print_in_order function works properly so I did not include it).
class Node:
def __init__(self, key):
self.key = key
self.left = None
self.right = None
def bst_insert(t, k):
if t is None:
t = Node(k)
elif k <= t.key:
if t.left is None:
t.left = Node(k)
else:
t.left = bst_insert(t.left, k)
else:
if t.right is None:
t.right = Node(k)
else:
t.right = bst_insert(t.right, k)
Thanks.
class Node:
def __init__(self, key):
self.key = key
self.left = None
self.right = None
def bst_insert(t, k):
if t is None:
t = Node(k)
elif k <= t.key:
if t.left is None:
t.left = Node(k)
else:
t.left = bst_insert(t.left, k) #1
else:
if t.right is None:
t.right = Node(k)
else:
t.right = bst_insert(t.right, k) #2
# return the node, #1 and #2 will always get None value
return t
from __future__ import annotations
class Node:
def __init__(self, value: int) -> None:
self.value = value
self.left = self.right = None
def __repr__(self) -> str:
return f"{self.__class__.__name__}({self.value})"
class BST:
def __init__(self):
self.root = None
def add(self, root: Node, value: int) -> Node:
# if there is not root (empty node) -> then create new one
if root is None:
return Node(value)
if value <= root.value:
root.left = self.add(root.left, value)
else:
root.right = self.add(root.right, value)
return root
def print(self, root: Node) -> None:
"""Prints inorders BST values."""
if root is None:
return
self.print(root.left)
print(root.value, end=" ")
self.print(root.right)
if __name__ == "__main__":
values = [10, 6, 12, 3, 7, 4, 2]
bst = BST()
root = None
for value in values:
root = bst.add(root, value)
bst.print(root)
# output
# 2 3 4 6 7 10 12
I want to print a binary tree level by level iteratively without using a dequeue or any other data structure besides a python list. I have looked online and most do it one of those ways mentioned above.
If I have a tree:
41
/ \
7 53
/ \ /
1 19 47
I want it to print like:
41
7
53
1
19
47
This is my shot at it but it doesn't print out all the values in the bst:
def levelorder(self):
current = self._root
current_left = current_right = self._root
a = [current._value]
while current_left is not None and current_right is not None:
current_left = current_left._left
current_right = current_right._right
if current_left is not None:
a.append(current_left._value)
if current_right is not None:
a.append(current_right._value)
return a
This is what it outputs:
[41, 7, 53, 1]
Any ideas what is wrong with my code? and how I can approach the solution to this problem?
TREE CLASS:
class _BSTNode:
def __init__(self, value):
self._value = copy.deepcopy(value)
self._left = None
self._right = None
self._height = 1
return
class BST:
def __init__(self):
self._root = None
self._count = 0
self.comparisons = 0
return
def levelorder(self):
levels = [[self._root]]
while levels[-1]:
nextlevel = []
for node in levels[-1]:
nextlevel.extend([node for node in (node._left, node._right) if node])
levels.append(nextlevel)
return levels[:-1]
and my main part:
b = BST()
b.insert(41)
b.insert(7)
b.insert(53)
b.insert(1)
b.insert(19)
b.insert(47)
print (b.levelorder())
Without testing, as I don't have your Tree class, but I hope the general idea applies:
def levelorder(tree):
levels = [ [tree.root] ]
while levels [-1]:
nextLevel = []
for node in levels [-1]:
nextLevel.extend ( [node for node in (node.left, node.right) if node] )
levels.append (nextLevel)
return levels # or maybe levels [:-1]
Fully working example:
#! /usr/bin/python3
class Node:
def __init__(self, payload, left = None, right = None):
self.payload = payload
self.left = left
self.right = right
def __repr__(self):
return self.payload
class Tree:
def __init__(self, root):
self.root = root
def levels(self):
levels = [[self.root]]
while levels[-1]:
nextLevel = []
for node in levels[-1]:
nextLevel.extend([node for node in (node.left, node.right) if node])
levels.append(nextLevel)
return levels[:-1]
t = Tree(Node('41', Node('7', Node('1'), Node('19')), Node('53', Node('47'))))
print(t.levels())
Output is [[41], [7, 53], [1, 19, 47]]