0

EDIT: I have overall finished the original problem. However I have a small problem. I will print out all of my code to show you all. The objective is print out all of the binary search tree parts in a list, plus every empty spot. The empty spots are represented by None. The problem is, the code prints out the list, however, there are three extra Nones at the end. It would be best if you just took the code and ran it on your own pc, as it is extremely hard to explain all of this.

class TreeNode:    
   def __init__(self, value, left_child=None, right_child=None, parent=None):
       self.value = value
       self.left_child = left_child
       self.right_child = right_child
       self.parent = parent

   def __repr__(self):
       return '{}'.format(self.value)

class binary_search_tree:

   def __init__(self):
       self.root=None 

   def insert(self, value):
       if self.root==None:
           self.root=TreeNode(value)
       else:
           self._insert(value, self.root)

   def _insert(self, value, current_node):
       if value < current_node.value:
           if current_node.left_child==None:
               current_node.left_child=TreeNode(value)
               current_node.left_child.parent=current_node #set parent
           else:
               self._insert(value, current_node.left_child)
       elif value > current_node.value:
           if current_node.right_child==None:
               current_node.right_child=TreeNode(value)
               current_node.right_child.parent=current_node #set parent
           else:
               self._insert(value, current_node.right_child)
       else:
           print("Value already in tree")

   def height(self):
       if self.root!=None:
           return self._height(self.root,0)
       else:
           return 0

   def _height(self, current_node, current_height):
       if current_node==None: return current_height
       left_height=self._height(current_node.left_child,current_height+1)
       right_height=self._height(current_node.right_child,current_height+1)
       return max(left_height, right_height)

   def height_iter(self):
       current_node = self.root
       if self.root != None:
           pass
           

   def print_tree(self):
       line = []
       if self.root!=None:
           line.append(self._print_tree(self.root))
       print(line)
            

   def _print_tree(self, current_node):

       if current_node!=None:
           self._print_tree(current_node.left_child)
           print(str(current_node.value))

           if current_node.left_child!=None:
               print(str(current_node.left_child.value))

           if current_node.right_child!=None:
               print(str(current_node.right_child.value))

           #node.display(current_node)
           self._print_tree(current_node.right_child)


   #returns the node with the specified input value
   def find(self, value):
       if self.root!=None:
           return self._find(value, self.root)
       else:
           return None

   #private find
   def _find(self, value, current_node):
       if value==current_node.value:
           return current_node
       elif value<current_node.value and current_node.left_child!=None:
           return self._find(value, current_node.left_child)
       elif value>current_node.value and current_node.right_child!=None:
           return self._find(value, current_node.right_child)
       

   def delete_value(self, value):
       return self.delete_node(self.find(value))

   def delete_node(self, node):

       #returns node with min in tree rooted at input node
       def min_value_node(n):
           current=n
           while current.left_child!=None:
               current=current.left_child
           return current
       
       #returns the number of children for the specified node
       def num_children(n):
           num_children=0
           if n.left_child!=None: 
               num_children+=1
           if n.right_child!=None: 
               num_children+=1
           return num_children

       #get the parent of the node to be deleted
       node_parent = node.parent

       #get the number of children of the node to be deleted
       node_children = num_children(node)

       #CASE 1 (node has no children)
       if node_children == 0:

           #remove the reference to the node from the parent
           if node_parent.left_child==node:
               node_parent.left_child=None
           else:
               node_parent.right_child=None

       #CASE 2 (node has 1 child)
       if node_children == 1:
           
           #get the populated node
           if node.left_child!=None:
               child=node.left_child
           else:
               child=node.right_child

           #replace the mode to be deleted with its child
           if node_parent.left_child==node:
               node_parent.left_child=child
           else:
               node_parent.right_child=child

           child.parent=node_parent

           #correct the parent pointer in node
           child.parent=node_parent

       #CASE 3 (node has two children)
       if node_children == 2:

           #get the in order successor of the deleted node
           successor=min_value_node(node.right_child)

           #copy the in order successor value to the node formerly
           #holding the value we tried to delete.
           node.value=successor.value

           #delete in order successor now that the value copied to other node
           self.delete_node(successor)

   #returns true if the value exists in the tree
   def search(self, value):
       if self.root!=None:
           return self._search(value, self.root)
       else:
           return False

   def _search(self, value, current_node):
       if value==current_node.value:
           return True
       elif value<current_node.value and current_node.left_child!=None:
           return self._search(value, current_node.left_child)
       elif value>current_node.value and current_node.right_child!=None:
           return self._search(value, current_node.right_child)
       return False 
       return type(value)

   # def sibling(self,root):
   #     while root != self.root:
   #         if root < self.root:
   #             root = self.root.left_child


   
   def search_iter(self, value):
       # if self.root.value == None:
       #     return False

       current_node = self.root
       if current_node.value == None:
           return False
       else:
       
           while (value != current_node.value):
               if value < current_node.value:
                   if current_node.left_child != None:
                       current_node = current_node.left_child
                   else:
                       return False
               elif value > current_node.value:
                   if current_node.right_child != None:
                       current_node = current_node.right_child
                   else:
                       return False
           
           return True

       
       
       

   #find the minimum element in the tree
   def min(self):
       if self.root == None:
           return False

       current_node = self.root
       while (current_node.left_child != None):
           current_node = current_node.left_child

       return current_node.value
   
   def min_rec(self):
       if self.root != None:
           return self._min_rec(self.root.left_child)
       else:
           return self.root.value

   def _min_rec(self, current_node):
       if current_node == None:
           return False
       elif current_node.left_child == None:
           return current_node.value
       else:
           return self._min_rec(current_node.left_child)
           

       
   def max_rec(self):
       if self.root != None:
           return self._max_rec(self.root.right_child)
       else:
           return self.root.value

   def _max_rec(self, current_node):
       if current_node.value == None:
           return False
       elif current_node.right_child == None:
           return current_node.value            
       else:
           return self._max_rec(current_node.right_child)
       

       
       
       # while (current_node.left_child != None):
       #     current_node = current_node.left_child

       # return current_node.value
       
   
   def max(self):
       if self.root == None:
           return False

       current_node = self.root
       while (current_node.right_child != None):
           current_node = current_node.right_child

       return current_node.value
   # Function to  print level order traversal of tree 
   def printLevelOrder(self): 
       from collections import deque
       level_lst = []
       queue = deque([ self.root ])
       while len(queue):
           node = queue.popleft()
           if node != None:
               level_lst.append(node.value)
           


           

           else:
               while node == None:
                   level_lst.append(None)
                   
               
                   
                   node = queue.popleft()
                   if node != None:
                       level_lst.append(node.value)
                   if len(queue) == 0:
                       
                       
                       break
                       
                       
          
               
                   
                  

           if node == None:
               if len(queue) == 0:
                   print (level_lst)
                       
                   break
           
           

           if node.left_child != None:
               queue.append(node.left_child)
           else:
               queue.append(None)


           if node.right_child != None:
               queue.append(node.right_child)
           else:
               queue.append(None)
       
               
       
       # root = self.root
       # level_lst = []
       # if not root:
       #     return level_lst
   
       # stack = []
       
      

       # while stack:
       #     stack.append(root.value)
       #     root = self.root.left_child
       #     level = stack.pop()
       #     curr_level = []
       #     next_level = []
       #     for node in level:
       #         curr_level.append(node.value)
       #         if node.left_child:
       #             next_level.append(node.left_child)
       #         if node.right_child:
       #             next_level.append(node.right_child)
       #             level_lst.append(curr_level)
       #             if next_level:
       #                 stack.append(next_level)
       
       #     return level_lst

       # root = self.root
       # level_lst = []
       # queue = []
       # queue.append(root.value)
       
       # heigh = self.height()
       # while queue:
       #     count = len(queue)
       #     level_lst.append(root)
       #     queue.append(root.value)
           
           
       #     while count > 0:
       #         queue.append(root.value)
       #         queue.pop(root.value)
       #         level_lst.append(root.value)
       #         if root.left_child == None:
       #             if root.right_child != None:
       #                 root = root.right_child
       #                 queue.append(root.value)
       #             elif root.right_child == None:
       #                 root = root.parent.right_child
       #         else:
       #             root = root.left_child
       #             queue.append(root.value)
       #     print(level_lst)
               
   # def printLevelOrder(self,root):
   #     if self.root != root:
           
   
   #     h = tree.height() 
   #     for i in range(1, h+1): 
   #         self.printGivenLevel(self.root.value, i) 
   # def printGivenLevel(self, root , level): 
   #     if root is None: 
   #         return
   #     if level == 1: 
   #         print(root,end=" ") 
   #     elif level > 1: 
   #         self.printGivenLevel(self.root.left_child , level-1) 
   #         self.printGivenLevel(self.root.right_child , level-1) 
               
 


       

#manually populate tree
tree = binary_search_tree()

#Fill tree with 100 random integers
def fill_tree(tree, num_elems, max_int):
   from random import randint
   for _ in range(num_elems):
       cur_elem = randint(0, max_int)
       tree.insert(cur_elem)
   return tree


#function to draw the tree
def drawtree(root):
   
   def height(root):
       return 1 + max(height(root.left_child), height(root.right_child)) if root else -1

   def jumpto(x, y):
       t.penup()
       t.goto(x, y)
       t.pendown()

   def draw(node, x, y, dx):
       if node:
           t.goto(x, y)
           jumpto(x, y-20)
           t.write(node.value, align='center', font=('Arial', 12, 'normal'))
           draw(node.left_child, x-dx, y-60, dx/2)
           jumpto(x, y-20)
           draw(node.right_child, x+dx, y-60, dx/2)

   import turtle
   t = turtle.Turtle()
   t.speed(0); turtle.delay(2)
   h = height(root)
   jumpto(0, 30*h)
   draw(root, 0, 30*h, 40*h)
   t.hideturtle()
   turtle.mainloop()



       
       
   
   

       
     
   

   

   
   

       
 
   

####################################
#BUILD A TREE (manual or automatic)
####################################

#Automatic Fill
# tree = binary_search_tree()
# tree = fill_tree(tree,100,100)


# #manually populate tree
# tree = binary_search_tree()
   


#order of insertion matters in terms of the tree you get : monotonically decreasing insertions
# tree.insert(12)
# tree.insert(10)
# tree.insert(7)
# tree.insert(5)
# tree.insert(2)
# tree.insert(1)
# #tree.insert(0)

# #add some extras and see what happens
# # tree.insert(4)
# # tree.insert(3)
# # tree.insert(7)
# tree.insert(20)



#here's another order of insertion, more mixed - try both to see the result
tree.insert(5)
tree.insert(1)
tree.insert(3)
tree.insert(2)
tree.insert(10)
tree.insert(0)
tree.insert(20)
tree.insert(7)
tree.insert(4)

#query the tree (for monotonically decreasing insertions)
# print(tree.root)
# print(tree.root.left_child)
# print(tree.root.left_child.left_child)
# print(tree.root.left_child.left_child.left_child)
# print(tree.root.left_child.left_child.left_child.left_child)
# print(tree.root.left_child.left_child.left_child.left_child.left_child)
# print(tree.root.left_child.left_child.left_child.left_child.left_child.left_child)

#tree height 
print("tree height: ",str(tree.height()))
# print("sibling of 10 is",tree.sibling(10))


#minimum element
print("minimum element in tree: ", tree.min())
print("maximum element in tree: ", tree.max_rec())
#print("maximum element in tree: ", tree.max())
print(tree.search_iter(1))
tree.printLevelOrder()

#print(tree.find(10))
#tree.delete_value(3)
#tree.delete_value(2)


#############
#DRAW A TREE 
#############
drawtree(tree.root)


               
  • 1
    You have to figure out a way to turn this into a minimal reproducible example. One way you could do this is to simply take the vars that do not exist in this method and include them with some static example values, just enough so this will run. Saying you can't post enough code is not acceptable. Find a way. Also, what doesn't work about it? Are you getting errors, unexpected results, incorrect values? You have to be more specific. – OneMadGypsy Jul 27 '20 at 15:35
  • You do `queue.pop(i)` will remove the item at that *index* from the list e.g. if `lst = [3, 4, 5, 6, 7]` then `lst.pop(3)` will leave `lst` having value `[3, 4, 5, 7]` because it removed the item at index `3`. I think it's unlikely `queue.pop(root.value)` does what you were hoping. – Arthur Tacca Jul 27 '20 at 16:24
  • Other problems: `queue` is empty when you first get to the `while` loop, so it's already "falsy" and the while loop won't run at all, even once. Your `pop` is straight after an `append`, so you end up just leaving the `queue` the same length, and you never remove any items anywhere else, so if you ever did get into that `while` loop then you'd never stop because the `queue` would just keep getting longer and longer. – Arthur Tacca Jul 27 '20 at 16:26
  • Rather than using one of the answers that others have generously posted here, I suggest you try to step back and think of what your strategy is (I don't think you have a real plan here, I think you've just thrown code at this in the hope it ends up working) and write code that follows that plan. You'll never learn to code properly if you don't do this for yourself. – Arthur Tacca Jul 27 '20 at 16:28

1 Answers1

1

You simply need the following:

from collections import deque

def printLevelOrder(self): 
    queue = deque([ self.root ])
    while len(queue):
        node = queue.popleft()

        print(node.value)

        if node.left_child != None:
            queue.append( ( node.left_child)
        if node.right_child != None:
            queue.append(node.right_child)

If you also want the level,

from collections import deque

def printLevelOrder(self): 
    queue = deque([ ( 0, self.root ) ])
    while len(queue):
        state = queue.popleft()
        level = state[0]
        node = state[1]

        print(level, node.value)

        if node.left_child != None:
            queue.append( ( level+1, node.left_child ) )
        if node.right_child != None:
            queue.append( ( level+1, node.right_child ) )

It's yet another simple modification to return values grouped by level.

from collections import deque

def printLevelOrder(self): 
    grouped = []

    queue = deque([ ( 0, self.root ) ])
    while len(queue):
        state = queue.popleft()
        level = state[0]
        node = state[1]

        if len(grouped) == level:
           grouped.append([])

        grouped[level].append(node.value)

        if node.left_child != None:
            queue.append( ( level+1, node.left_child ) )
        if node.right_child != None:
            queue.append( ( level+1, node.right_child ) )

    return grouped
ikegami
  • 367,544
  • 15
  • 269
  • 518