Advertisement
zinch

Segment Tree

Apr 22nd, 2014
351
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 3.97 KB | None | 0 0
  1. import java.util.Arrays;
  2.  
  3. public class SegmentTree {
  4.  
  5.     private final int[] data;
  6.  
  7.     SegmentTree(final int[] values) {
  8.  
  9.         int x = 1;
  10.         //Search for the first
  11.         //power of 2 greater then n
  12.         while (x < values.length) {
  13.             x *= 2;
  14.         }
  15.  
  16.         data = new int[2 * x - 1];
  17.         for (int i = 0; i < data.length; i++) {
  18.             data[i] = Integer.MAX_VALUE; //Infinity
  19.         }
  20.         System.arraycopy(values, 0, data, getOffset(), values.length);
  21.  
  22.         //Restore invariants
  23.         int offset = getOffset();
  24.  
  25.         //Count of nodes to be examined
  26.         int limit = data.length - offset - 1;
  27.         while (limit >= 1) {
  28.             for (int i = 0; i < limit; i += 2) {
  29.                 final int left = i + offset;
  30.                 final int right = left + 1;
  31.                 final int min = Math.min(data[left], data[right]);
  32.  
  33.                 //Change parents value to the minimum of its children
  34.                 int parentIdx = (left + 1) / 2 - 1;
  35.                 data[parentIdx] = min;
  36.             }
  37.  
  38.             limit >>>= 1; //Proceed twice as less as in current step
  39.             offset = (offset + 1) / 2 - 1; //Move one level up the heap
  40.         }
  41.  
  42.     }
  43.  
  44.     public int min(final int left, final int right) {
  45.  
  46.         final int rangeEnd = data.length - data.length / 2;
  47.  
  48.         return getMinOnRange(1, rangeEnd, left, right);
  49.     }
  50.  
  51.     private int getMinOnRange(final int rangeStart, final int rangeEnd,
  52.                               final int left, final int right)
  53.     {
  54. //            System.out.println("[" + rangeStart + ", " + rangeEnd + "]");
  55. //            System.out.println("(" + left + ", " + right + ")");
  56.  
  57.         if (left == right) return getSingleValue(left);
  58.  
  59.         if (rangeStart == left && rangeEnd == right) {
  60.             return getCachedValue(rangeStart, rangeEnd);
  61.         }
  62.  
  63.         final int mid = (rangeStart + rangeEnd) / 2; //Mid is always even
  64.  
  65.         if (mid > left && mid < right) {
  66.  
  67.             return Math.min(getMinOnRange(rangeStart, mid, left, mid),
  68.                     getMinOnRange(mid + 1, rangeEnd, mid + 1, right));
  69.  
  70.         } else if (mid < left) {
  71.  
  72.             return getMinOnRange(mid + 1, rangeEnd, left, right);
  73.  
  74.         } else if (mid >= right) {
  75.  
  76.             return getMinOnRange(rangeStart, mid, left, right);
  77.  
  78.         } else {
  79.  
  80.             return Math.min(getMinOnRange(rangeStart, mid, left, mid),
  81.                     getMinOnRange(mid + 1, rangeEnd, mid + 1, right));
  82.         }
  83.     }
  84.  
  85.     private int getSingleValue(final int idx) {
  86.         return data[getOffset() + idx - 1];
  87.     }
  88.  
  89.     private int getCachedValue(final int rangeStart, final int rangeEnd) {
  90.         int diff = rangeEnd - rangeStart + 1;
  91.         int realIdx = getOffset() + rangeStart - 1;
  92.  
  93.         while (diff > 1) {
  94.             //Move to the
  95.             realIdx = (realIdx + 1) / 2 - 1;
  96.             diff /= 2;
  97.         }
  98.  
  99.         return data[realIdx];
  100.     }
  101.  
  102.     public void set(final int pos, final int value) {
  103.         final int offset = getOffset();
  104.         final  int realIdx = offset + pos - 1;
  105.         data[realIdx] = value;
  106.  
  107.         restoreInvariant(realIdx);
  108.     }
  109.  
  110.     public String toString() {
  111.         return Arrays.toString(data).replaceAll(
  112.                 String.valueOf(Integer.MAX_VALUE),
  113.                 "inf"
  114.         );
  115.     }
  116.  
  117.     private int getOffset() {
  118.         //Leaves of the heap
  119.         //start from this index
  120.         //Heap size is 2^n - 1 thus
  121.         //offset points exactly to the first leave
  122.         return data.length / 2;
  123.     }
  124.  
  125.     private void restoreInvariant(final int idx) {
  126.         //If root then return
  127.         if (idx == 0) {
  128.             return;
  129.         }
  130.  
  131.         final int left = ((idx & 1) == 0) ? idx - 1: idx;
  132.         final int right = left + 1;
  133.         final int parentIdx = (left + 1) / 2 - 1;
  134.  
  135.         data[parentIdx] = Math.min(data[left], data[right]);
  136.  
  137.         restoreInvariant(parentIdx);
  138.     }
  139. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement