0

I have this algorithm which I modeled off of https://cp-algorithms.com/data_structures/segment_tree.html#structure-of-the-segment-tree.

nums = [1,3,-2,8,-7]

N = len(nums)
tree = [0] * (N* 4)

def build_iterative():
    
    for i in range(N):
        tree[i + N] = nums[i]
    # then you set the parents
    for j in range(N - 1, 0, -1):
        tree[j] = tree[j * 2] + tree[j * 2 + 1]
build_iterative()

But it only works for perfect trees aka any array that is a power of 2, but fails for anything that is not perfect. I am not sure why this is the case and cannot figure out what I am missing. Why does this algorithm only work for perfect binary trees? A recursive version will create the correct segment tree array regardless of perfect or full.

Recursive algorithm for comparison which works for any tree perfect or full.

rtree = [0] * (4 * N)
def build_recursively(node, left, right):
    if left == right:
        rtree[node] = nums[left]
    else:
        mid = (left + right) // 2
        build_recursively(node * 2, left, mid)
        build_recursively(node * 2 + 1, mid + 1, right)
        rtree[node] = rtree[node * 2] + rtree[node * 2 + 1]

build_recursively(1, 0, N - 1)
Paul
  • 1,101
  • 1
  • 11
  • 20
  • What do you mean it "fails"? What do you expect `tree` to contain after the first `for` loop, and what does it actually contain? Likewise for the second `for` loop. – Beta Aug 10 '22 at 00:20
  • @Beta I expect tree to have the correct segment tree for sum queries. – Paul Aug 10 '22 at 17:56

1 Answers1

0

Consider the indices in a binary representation.

1011 --> parent

10110 --> left child

10111 --> right child

Similarly for a complete binary tree, if it is starting with index-1, for an index k, we can represent left child as (k << 1) which is 2k and right child as ((k << 1) + 1) which is 2k+1. But if you want to construct such for an array with length ≠ $2^n$, some nodes without maximum depth do not contain left child or right child, so the pattern breaks for them.

To preserve such structure, 4N nodes were used in the code and the redundant nodes are filled with 0 in this segment tree for range sum queries, $infty$ for range minimum queries.
In general if f(c, x) = x for all x, replace redundant values with c.

To use optimal space, recursion is required in building and querying the tree.

Programmer
  • 41
  • 3