Segment Tree Implementation in Bash

This document explains how to implement a Segment Tree using Bash. A Segment Tree is a data structure that allows for efficient range queries and updates on an array. It is widely used in scenarios where we need to repeatedly calculate sums, minimums, maximums, or other aggregate functions over a range of elements.

Program Structure

The program is structured into several key functions:

  • initialize_tree: Initializes the Segment Tree with a given array.
  • build_tree: Recursively builds the Segment Tree.
  • range_query: Queries the Segment Tree for a range sum.
  • update_tree: Updates the Segment Tree when an element in the array changes.

Implementation


#!/bin/bash

# Initialize the Segment Tree
initialize_tree() {
    local arr=("$@")
    n=${#arr[@]}
    segment_tree=()
    build_tree arr 0 $((n - 1)) 0
}

# Recursively build the Segment Tree
build_tree() {
    local arr=("$@")
    local start=$2
    local end=$3
    local node=$4

    if [ $start -eq $end ]; then
        segment_tree[$node]=${arr[$start]}
    else
        local mid=$(( (start + end) / 2 ))
        local left_child=$(( 2 * node + 1 ))
        local right_child=$(( 2 * node + 2 ))
        
        build_tree arr $start $mid $left_child
        build_tree arr $((mid + 1)) $end $right_child
        
        segment_tree[$node]=$(( segment_tree[$left_child] + segment_tree[$right_child] ))
    fi
}

# Range query for sum
range_query() {
    local query_start=$1
    local query_end=$2
    query_tree 0 0 $((n - 1)) $query_start $query_end
}

# Recursively query the tree
query_tree() {
    local node=$1
    local start=$2
    local end=$3
    local query_start=$4
    local query_end=$5

    if [ $query_start -le $start ] && [ $query_end -ge $end ]; then
        echo ${segment_tree[$node]}
        return
    fi

    if [ $query_start -gt $end ] || [ $query_end -lt $start ]; then
        echo 0
        return
    fi

    local mid=$(( (start + end) / 2 ))
    local left_child=$(( 2 * node + 1 ))
    local right_child=$(( 2 * node + 2 ))

    local left_sum=$(query_tree $left_child $start $mid $query_start $query_end)
    local right_sum=$(query_tree $right_child $((mid + 1)) $end $query_start $query_end)

    echo $(( left_sum + right_sum ))
}

# Update the Segment Tree
update_tree() {
    local index=$1
    local value=$2
    update_recursive 0 0 $((n - 1)) $index $value
}

# Recursively update the tree
update_recursive() {
    local node=$1
    local start=$2
    local end=$3
    local index=$4
    local value=$5

    if [ $start -eq $end ]; then
        segment_tree[$node]=$value
    else
        local mid=$(( (start + end) / 2 ))
        local left_child=$(( 2 * node + 1 ))
        local right_child=$(( 2 * node + 2 ))
        
        if [ $index -le $mid ]; then
            update_recursive $left_child $start $mid $index $value
        else
            update_recursive $right_child $((mid + 1)) $end $index $value
        fi

        segment_tree[$node]=$(( segment_tree[$left_child] + segment_tree[$right_child] ))
    fi
}

# Example usage
initialize_tree 1 3 5 7 9 11

echo "Segment Tree: ${segment_tree[@]}"

# Query the sum of the range [1, 3]
echo "Sum of range [1, 3]: $(range_query 1 3)"

# Update index 1 to value 10
update_tree 1 10
echo "Segment Tree after update: ${segment_tree[@]}"

# Query the sum of the range [1, 3] again
echo "Sum of range [1, 3] after update: $(range_query 1 3)"
    

Explanation

The program implements a basic Segment Tree with the following components:

Initialization

The initialize_tree function sets up the Segment Tree for a given array. It calculates the size of the array and calls the build_tree function to recursively build the Segment Tree.

Building the Tree

The build_tree function recursively divides the array into segments and stores the sum of each segment in the Segment Tree. The leaves of the tree represent individual elements of the array, and each internal node represents the sum of a range of elements.

Range Queries

The range_query function queries the Segment Tree to find the sum of elements within a specified range. It calls the query_tree function, which recursively checks if the current segment overlaps with the query range and returns the appropriate sum.

Updating the Tree

The update_tree function updates the Segment Tree when an element in the array changes. It calls the update_recursive function, which recursively updates the value in the tree and recalculates the sums of the affected segments.

Example Usage

The example usage section demonstrates how to initialize a Segment Tree with an array of six elements, perform a range query on the sum of elements from index 1 to 3, update an element in the array, and perform the range query again to see the updated sum. The program outputs the Segment Tree structure and the results of the queries.

Conclusion

This Bash implementation of a Segment Tree provides a powerful tool for efficiently handling range queries and updates on an array. Segment Trees are particularly useful in scenarios where we need to perform multiple range queries and updates, such as in interval management, statistical analysis, and gaming applications.

 

By Aditya Bhuyan

I work as a cloud specialist. In addition to being an architect and SRE specialist, I work as a cloud engineer and developer. I have assisted my clients in converting their antiquated programmes into contemporary microservices that operate on various cloud computing platforms such as AWS, GCP, Azure, or VMware Tanzu, as well as orchestration systems such as Docker Swarm or Kubernetes. For over twenty years, I have been employed in the IT sector as a Java developer, J2EE architect, scrum master, and instructor. I write about Cloud Native and Cloud often. Bangalore, India is where my family and I call home. I maintain my physical and mental fitness by doing a lot of yoga and meditation.

Leave a Reply

Your email address will not be published. Required fields are marked *

error

Enjoy this blog? Please spread the word :)