Python – Usage of a Binary Tree with List in Python

After the article here, concerning the building of the binary trees and their usefulness, today I will show how to use these trees in action 🙂

300px-Binary_tree.svg

Imagine that we have the following problem, used in arena.hackbulgaria.com:


Implement a program in Java, Python or C++ which starts with an initial list of number and then implements the following two commands. set [index] [value] – replaces the value at index in the list with the specified value. index <= length of the list. min [start_index] [end_index] – returns the minimum value from the elements between start_index and end_index. start_index <= end_index. Indices in both operations are zero-based. The first line of the input will contain two integers – the length of the list and the number of commands. The second line of the input will contain the elements of the list, separated by space. Each of the following lines will contain a single command in the format specified above.

Example
Input Output
16 8
19 11 15 4 7 13 11 2 3 5 12 7 23 17 4 6
min 0 4 4
min 5 10 2
set 4 3
min 4 8 2
min 0 6 3
set 15 8
min 15 15 8
min 10 13 7

And I have managed to achieve it with the help of a binary tree:

binaryTree

 

What have I done? Pretty much, I have made the following functions, to help me build the tree. This is their explanation, although their names are self-explanatory:

import math

def locate_parent(position,levels):
    #Locates a parent of the position, taking into account the levels above.

def logarithm(n):
    #log base 2 of n is m

def is_left(number):
    #answers whether the branch is left (true) or right

def get_parent_on_levels(node,level):
    #returns the node, on which a parent is located. 
    #or a grandparent, if the level is 2 :)

def set_value(position, number):
    #sets a value in the initial array.
    #then rebuilds part of the tree, to make sure it is still working

def create_a_binary_tree(list_first_line):
    #creates a binary tree from the given input

def parent_in_range(node_parent,a,b,level):
    #checks whether a node is a parent of given 2 other nodes.
    #levels are taken into account as well

def get_left_and_right_children(node, level):
    #gets the child which is in the leftmost position
    #and the child in the rightmost
    #concerning the level

def locate_minimal(a, b):
  #locates minimal value within two nodes

Pretty much, that is all. 🙂 The functions work as they are supposed to.

If you need the whole code, it is available in GitHub here:

Or simply below:

import math

def locate_parent(position,levels):
    #Locates a parent of the position, taking into account the levels above.
    for i in range (0 ,levels):
        position = int((position-1)/2)
    return position

def logarithm(n):
    #log base 2 of n is m
    return int(math.log(n,2))

def is_left(number):
    #answers whether the branch is left (true) or right
    if number%2 ==1:
        return True
    else:
        return False

def get_parent_on_levels(node,level):
    #returns the node, on which a parent is located. 
    #or a grandparent, if the level is 2 :)
    while level>0:
        node = int((node-1)/2)
        level-=1
    return node

def set_value(position, number):
    #sets a value in the initial array.
    #then rebuilds part of the tree, to make sure it is still working
    position = starting_position+position
    tree[position] = number

    our_number = number
    our_position = position    
    
    while(True) and our_position != 0:     
        
        if is_left(number):
            compare_with = tree[our_position+1]
        else:
            compare_with = tree[our_position-1]
        
        if number= 0:
        tree[start_at] = min(tree[2*start_at+1], tree[2*start_at+2])
        start_at -= 1
    
    return tree

def parent_in_range(node_parent,a,b,level):
    #checks whether a node is a parent of given 2 other nodes.
    #levels are taken into account as well
    list_children = get_left_and_right_children(node_parent,level)
    if list_children[0]>=a and list_children[1]<=b:
        return True
    return False

def get_left_and_right_children(node, level):
    #gets the child which is in the leftmost position
    #and the child in the rightmost
    #concerning the level
    nodeRightChild = node
    nodeLeftChild = node
    
    while level>0:
        nodeLeftChild = 2*nodeLeftChild + 1
        nodeRightChild  = 2*nodeRightChild +2
        level-=1
    return ([nodeLeftChild, nodeRightChild])

#Input starts here
list_n_and_k = list(input().split())
list_n_and_k = list(map(int, list_n_and_k))

list_first_line = list(input().split())
list_first_line = list(map(int, list_first_line))

total_entries = list_n_and_k[1]
list_orders = []

for i in range (0, total_entries):
    order = []
    order = list(input().split())
    
    if order[0] != "min":
        order[0] = 0
    else:
        order[0] = 1
    
    order[1] = int(order[1])
    order[2] = int(order[2])
    list_orders.append(order)
#Input ends here

tree = create_a_binary_tree(list_first_line)
starting_position = int(len(tree)/2)

def locate_minimal(a, b):
  #locates minimal value within two nodes
    a+= starting_position
    b+= starting_position
    result = []
    
    if a%2 == 0:
        result.append( tree[a])
        a+=1
    if b%2 == 1:
        result.append(tree[b])
        b-=1
    while (a

Enjoy it!