How is the memory of the array of segment tree 2 * 2 ^(ceil(log(n))) - 1?

后端 未结 6 620
半阙折子戏
半阙折子戏 2021-01-30 03:21

The link: http://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/. This is the quoted text:

We start with a segment arr[0 . . . n-1]. And ever

6条回答
  •  既然无缘
    2021-01-30 03:59

    Oddly enough, I was reading from the same source as the question when I came upon this. I'll try and answer my best.

    Let's start with a basic difference in trees representations (in context only):

    1. The almost "Worst Case" scenario. This one is not completely balanced and not really fun to traverse. Why? Because, with different inputs, different trees might be generated and hence time taken to traverse is not very predictable. Almost worst case.

    2. Our "Best Case" scenario. This one is totally balanced or complete and will take a predictable amount of time to traverse, always. Moreover, this tree is also better "hacked". Best case.

    Now let's get back to our question. [Refer to the first image] We know that for every n-input array (The numbers in green), there will be n-1 internal nodes (The numbers in blue). So a maximum of 2n-1 node space must be allocated.

    But the code here does something on the contrary. Why and how?

    1. What you expect: You expect that the memory allocated for 2n-1 nodes should be sufficient. In other words, this should be done:

      int *st = new int[2*n - 1];
      

      Assuming the rest of the code works well, this is isn't a very good idea. That's because it creates our unbalanced tree, much like in our first case. Such a tree is not easy to traverse nor easy to apply to problem-solving.

    2. What really happens: We add/pad extra memory with null or 0 values. We do this:

      int x = (int)(ceil(log2(n))); //Height of segment tree
      int max_size = 2*(int)pow(2, x) - 1; //Maximum size of segment tree
      int *st = new int[max_size];
      

      That is we allocate enough space to generate a balanced complete tree. Such a tree is easy to traverse (using some special modifications) and can be applied to problems directly.

    How did we allocate enough memory for case 2? Here's how:

    • We know there are at least three components in our balanced Segment Tree:

      1. n numbers from our input array.
      2. n-1 internal nodes which are mandatorily required.
      3. The extra space we need to allocate for our padding.
    • We also know that a balanced tree with k leaves will have: tree LaTeX

    • Combining the two we get the desired outcome:

      int x = (int)(ceil(log2(n))); //Height of segment tree
      int max_size = 2*(int)pow(2, x) - 1; //Maximum size of segment tree
      int *st = new int[max_size];
      

    Trivia! Raising 2 to the power of x above, ensures that we get the nearest ceiling integer which is:

    1. Greater than or equal to n (Number of elements in our input array).
    2. Is perfectly and repeatedly divisible by 2, to get a completely balanced 2-ary (binary) tree.

提交回复
热议问题