Level Order Traversal - Tree - python

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

Related

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, >

How to return a list of lists in recursive function in Python

I am playing around with some toy code in Python. But somehow cant get through. I am using a recursion in a Tree data structure to generate paths from a particular node to each children leaf nodes.
The idea behind the recursive function is to have a list which would collect each path to the individual leaf node and then collect each paths in another list.
class Tree:
def __init__(self):
self._ancestors = []
self._store_nodes = {}
def add_node(self, node):
assert isinstance(node, Node)
self._store_nodes[node.name] = node
def get_c_path(self, node):
subpath = []
path = []
path = self.ret_path(node, subpath, path)
return path
## recursive function to fetch paths
def ret_path(self, node, subpath=[], pathstore=[]):
if len(node.children) == 0:
pathstore.append(subpath)
return
else:
for c in node.children:
subpath.append(c)
self.ret_path(c, subpath, pathstore)
class Node(object):
def __init__(self, name=''):
self._name = name
self._children = set([])
self._parents = set([])
#property
def name(self):
return self._name
#property
def children(self):
return self._children
#property
def parents(self):
return self._parents
def add_child(self, node):
assert isinstance(node, Node)
self._children.add(node)
def add_parent(self, node):
assert isinstance(node, Node)
self._parents.add(node)
if __name__ == '__main__':
node_store = {1 : [2,3,4,5,6], 6 : [7,2,8,9,5], 2 : [10,11,5], 12 : [13,14,15,16], 5 : [21,22,23]}
tree = Tree()
## build the tree and set parents and children of each node
for k, v in node_store.items():
parent_node = None
if k in tree._store_nodes:
parent_node = tree._store_nodes[k]
else:
parent_node = Node(k)
tree.add_node(parent_node)
for c in v:
child_node = None
if c in tree._store_nodes:
child_node = tree._store_nodes[c]
else:
child_node = Node(c)
tree.add_node(child_node)
parent_node.add_child(child_node)
child_node.add_parent(parent_node)
print '-------------'
path = tree.get_c_path(tree._store_nodes[2])
for p in path:
for t in p:
print t.name
print "-----"
The result I am expecting is a list of list for Node-2 as follows:
path = [[10], [11], [5, 21], [5, 22], [5, 23]]
How can I correct my recursive function?
Here's two methods that would accomplish this goal. I'm not quite sure how to fix your structure; it seemed easier to start from scratch.
def get_c_path(self, node):
branches = [[c] for c in node.children]
expanded = self.expand_branches(branches)
while branches != expanded:
branches = expanded
expanded = self.expand_branches(expanded)
return expanded
def expand_branches(self, branches):
new_branches = []
for branch in branches:
last_node = branch[-1]
if last_node.children:
for child in last_node.children:
new_branches.append(branch + [child])
else:
new_branches.append(branch)
return new_branches

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])

Deleting the last element in my linked list

I've created a list using only the Node class
class Node:
def __init__(self, init_data):
self.data = init_data
self.next = None
def get_data(self):
return self.data
def get_next(self):
return self.next
def set_data(self, new_data):
self.data = new_data
def set_next(self, new_next):
self.next = new_next
def __str__(self):
return str(self.data)
I've intialized the list and the last Node is None.
I'm trying to delete this node but don't know how to?
One good way to do this is to keep track of the previous node and the current node, and then when you reach the end of the list, set the next of the previous to None.
prev = None
cur = head
while cur.next is not None:
prev = cur
cur = cur.next
if prev: #in case the head is the tail
prev.next = None
You'll probably want a List class to manage your nodes.
class List:
def __init__(self):
self._nodes = None
def push(self, node):
node.set_next(self._nodes)
self._nodes = node
return self
def pop(self):
if self._nodes is None:
return None
temp = self._nodes
self._nodes = temp.get_next()
return temp
def __len__(self):
l = 0
n = self._nodes
while n is not None:
n = n.get_next()
l += 1
return l
def remove(self, node):
n = self._nodes
p = None
while n is not None:
if n is node:
p.set_next(n.get_next())
n.set_next(None)
return True
p = n
n = n.get_next()
return False
def del_from_end(self):
if self.head is None:
return "No node to delete"
else:
current = self.head
while current.next.next is not None:
current = current.next
current.next = None
Add this method in your linked list class which would look like
class LinkedList():
def __init__(self, head=None):
if head == "" or head is None:
self.head = None
else:
self.head = Node(head)

Output BST in Nested Form

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.

Categories