Advertisement
Guest User

DuoHeap

a guest
Oct 19th, 2014
472
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.95 KB | None | 0 0
  1. package test;
  2.  
  3. import java.util.Comparator;
  4. import java.util.Random;
  5. import java.util.TreeSet;
  6.  
  7. public class DoubleQueueTest {
  8.     private void main() {
  9.         // long seed = 0xd6592198ce49bf7dL;
  10.         long seed = new Random().nextLong();
  11.         System.out.println("Seed: " + Long.toUnsignedString(seed, 16));
  12.         ran = new Random(seed);
  13.  
  14.         Comparator<Complex> c1 = Comparator.comparingInt(Complex::getReal)
  15.                 .thenComparingInt(Complex::getId);
  16.         Comparator<Complex> c2 = Comparator.comparingInt(Complex::getImaginary)
  17.                 .thenComparingInt(Complex::getId);
  18.  
  19.         DuoHeapDoubleQueue<Complex> heap = new DuoHeapDoubleQueue<>();
  20.  
  21.         heap.init(c1, c2);
  22.  
  23.         // correctness test
  24.         for (int i = 0; i < 13000; i++) {
  25.             Complex c = rand();
  26.             System.out.println("Epoch: " + i + ", generated: " + c);
  27.             heap.add(c);
  28.             if (i > 0 && i % 5 == 0) {
  29.                 heap.poll1();
  30.             }
  31.             if (i > 0 && i % 7 == 0) {
  32.                 heap.poll2();
  33.             }
  34.             System.out.println("Peek1: " + heap.peek1());
  35.             System.out.println("Peek2: " + heap.peek2());
  36.             heap.inspect();
  37.         }
  38.  
  39.         System.out.println("Inspection fails: " + inspectionFails);
  40.         System.out.println("Inspection checks: " + inspectionChecks);
  41.  
  42.         // performace test
  43.         ran.setSeed(seed);
  44.         DuoHeapDoubleQueue<Complex> heap1 = new DuoHeapDoubleQueue<>();
  45.         heap1.init(c1, c2);
  46.         long start1 = System.nanoTime();
  47.         for (int i = 0; i < 13000; i++) {
  48.             Complex c = rand();
  49.             heap1.add(c);
  50.             if (i > 0 && i % 5 == 0) {
  51.                 heap1.poll1();
  52.             }
  53.             if (i > 0 && i % 7 == 0) {
  54.                 heap1.poll2();
  55.             }
  56.         }
  57.         long end1 = System.nanoTime();
  58.         System.out.println("Duo heap: " + (end1 - start1));
  59.  
  60.         // performace test, part 2
  61.         ran.setSeed(seed);
  62.         Priority2Queue<Complex> heap2 = new Priority2Queue<>(c1, c2);
  63.         long start2 = System.nanoTime();
  64.         for (int i = 0; i < 13000; i++) {
  65.             Complex c = rand();
  66.             heap2.add(c);
  67.             if (i > 0 && i % 5 == 0) {
  68.                 heap2.poll1();
  69.             }
  70.             if (i > 0 && i % 7 == 0) {
  71.                 heap2.poll2();
  72.             }
  73.         }
  74.         long end2 = System.nanoTime();
  75.         System.out.println("Duo tree: " + (end2 - start2));
  76.     }
  77.  
  78.     class Foo {
  79.         Foo() {
  80.             super();
  81.         }
  82.     }
  83.  
  84.     private Random ran;
  85.     private int min = -100, max = 100;
  86.  
  87.     private Complex rand() {
  88.         int r = ran.nextInt(max - min + 1) + min;
  89.         int i = ran.nextInt(max - min + 1) + min;
  90.         return new Complex(r, i);
  91.     }
  92.  
  93.     private static class Complex {
  94.         private int real;
  95.         private int imaginary;
  96.         private int id;
  97.         private static int idCount = 0;
  98.  
  99.         public int getReal() {
  100.             return real;
  101.         }
  102.  
  103.         public int getImaginary() {
  104.             return imaginary;
  105.         }
  106.  
  107.         public int getId() {
  108.             return id;
  109.         }
  110.  
  111.         @Override
  112.         public int hashCode() {
  113.             final int prime = 31;
  114.             int result = 1;
  115.             result = prime * result + imaginary;
  116.             result = prime * result + real;
  117.             result = prime * result + id;
  118.             return result;
  119.         }
  120.  
  121.         @Override
  122.         public String toString() {
  123.             return "Complex [real=" + real + ", imaginary=" + imaginary
  124.                     + ", id=" + id + "]";
  125.         }
  126.  
  127.         @Override
  128.         public boolean equals(Object obj) {
  129.             if (this == obj)
  130.                 return true;
  131.             if (obj == null)
  132.                 return false;
  133.             if (getClass() != obj.getClass())
  134.                 return false;
  135.             Complex other = (Complex) obj;
  136.             if (imaginary != other.imaginary)
  137.                 return false;
  138.             if (real != other.real)
  139.                 return false;
  140.             if (id != other.id)
  141.                 return false;
  142.             return true;
  143.         }
  144.  
  145.         public Complex(int real, int imaginary) {
  146.             this.real = real;
  147.             this.imaginary = imaginary;
  148.             id = idCount++;
  149.         }
  150.     }
  151.  
  152.     public static void main(String[] args) {
  153.         new DoubleQueueTest().main();
  154.     }
  155.  
  156.     private interface DoubleQueue<T> {
  157.  
  158.         public void init(Comparator<? super T> c1, Comparator<? super T> c2);
  159.  
  160.         public void add(T e);
  161.  
  162.         public T peek1();
  163.  
  164.         public T peek2();
  165.  
  166.         public T poll1();
  167.  
  168.         public T poll2();
  169.     }
  170.  
  171.     private int inspectionFails = 0;
  172.     private long inspectionChecks = 0;
  173.  
  174.     private class DuoHeapDoubleQueue<T> implements DoubleQueue<T> {
  175.         private Comparator<? super T>[] cs;
  176.  
  177.         private T[][] data;
  178.         private int[][] links;
  179.  
  180.         private int count; // 1 = no items
  181.         private static final int CAPACITY = 10000;
  182.  
  183.         @SuppressWarnings({ "unchecked" })
  184.         @Override
  185.         public void init(Comparator<? super T> c1, Comparator<? super T> c2) {
  186.  
  187.             cs = new Comparator[2];
  188.             cs[0] = c1;
  189.             cs[1] = c2;
  190.  
  191.             data = (T[][]) new Object[2][CAPACITY + 1];
  192.  
  193.             links = new int[2][CAPACITY + 1];
  194.  
  195.             count = 1;
  196.         }
  197.  
  198.         /**
  199.          * swaps elements in one heap and sets links accordingly
  200.          *
  201.          * @param heapID
  202.          *            0 or 1
  203.          * @param pos0
  204.          *            indexed from 1
  205.          * @param pos1
  206.          *            indexed from 1
  207.          */
  208.         private void swap(int heapID, int pos0, int pos1) {
  209.             // acctual swap
  210.             T[] heap = data[heapID];
  211.             T tmp = heap[pos0];
  212.             heap[pos0] = heap[pos1];
  213.             heap[pos1] = tmp;
  214.  
  215.             // index update 1, swapping via XOR
  216.             int[] links = this.links[heapID];
  217.             links[pos0] ^= links[pos1];
  218.             links[pos1] ^= links[pos0];
  219.             links[pos0] ^= links[pos1];
  220.  
  221.             // index update 2
  222.             int[] links2 = this.links[1 - heapID];
  223.             links2[links[pos0]] = pos0;
  224.             links2[links[pos1]] = pos1;
  225.         }
  226.  
  227.         private int parent(int position) {
  228.             return position >>> 1;
  229.         }
  230.  
  231.         private int right(int position) {
  232.             return (position << 1) + 1;
  233.         }
  234.  
  235.         private int left(int position) {
  236.             return position << 1;
  237.         }
  238.  
  239.         private boolean exists(int position) {
  240.             return position > 0 && position < count;
  241.         }
  242.  
  243.         @Override
  244.         public void add(T e) {
  245.             if (count > CAPACITY) {
  246.                 System.err.println("FULL");
  247.                 return;
  248.             }
  249.             data[0][count] = data[1][count] = e;
  250.             links[0][count] = links[1][count] = count;
  251.  
  252.             count++;
  253.  
  254.             bubbleUpAt(0, count - 1);
  255.             bubbleUpAt(1, count - 1);
  256.         }
  257.  
  258.         private void bubbleUpAt(int heapID, int pos) {
  259.             if (pos == 1) { // root
  260.                 return;
  261.             }
  262.             T[] heap = data[heapID];
  263.             int parent = parent(pos);
  264.             if (cs[heapID].compare(heap[pos], heap[parent]) >= 0) {
  265.                 // parent is lower or equal
  266.                 return;
  267.             }
  268.             swap(heapID, pos, parent);
  269.             bubbleUpAt(heapID, parent);
  270.         }
  271.  
  272.         public void inspect() {
  273.             System.out.println("  --  INSPECTION START  --  ");
  274.             inspectHeap(0);
  275.             inspectHeap(1);
  276.             inspectLinks(0);
  277.             inspectLinks(1);
  278.             System.out.println("  --   INSPECTION END   --  ");
  279.         }
  280.  
  281.         private void inspectHeap(int heapID) {
  282.             System.out.println("  - inspecting heap: " + heapID);
  283.             for (int i = 1; i <= count; i++) {
  284.                 inspectNode(heapID, i);
  285.             }
  286.         }
  287.  
  288.         private void inspectNode(int heapID, int pos) {
  289.             int left = left(pos);
  290.             int right = right(pos);
  291.  
  292.             T[] heap = data[heapID];
  293.             if (exists(left)) {
  294.                 if (cs[heapID].compare(heap[pos], heap[left]) > 0) {
  295.                     System.out.format(
  296.                             "   ! inspection FAIL in heap %d at pos %d%n",
  297.                             heapID, pos);
  298.                     err();
  299.                 }
  300.             }
  301.             if (exists(right)) {
  302.                 if (cs[heapID].compare(heap[pos], heap[right]) > 0) {
  303.                     System.out.format(
  304.                             "   ! inspection FAIL in heap %d at pos %d%n",
  305.                             heapID, pos);
  306.                     err();
  307.                 }
  308.             }
  309.             inspectionChecks++;
  310.         }
  311.  
  312.         private void inspectLinks(int id) {
  313.             System.out.println("  - inspecting links: " + id);
  314.             T[] heap = data[id];
  315.             T[] heap2 = data[1 - id];
  316.             int[] links = this.links[id];
  317.             for (int i = 1; i < count; i++) {
  318.                 if (heap[i] != heap2[links[i]]) {
  319.                     System.out.format(
  320.                             "   ! inspection FAIL in links %d at pos %d%n", id,
  321.                             i);
  322.                     err();
  323.                 }
  324.             }
  325.             inspectionChecks++;
  326.         }
  327.  
  328.         private void err() {
  329.             inspectionFails++;
  330.         }
  331.  
  332.         @Override
  333.         public T peek1() {
  334.             return count == 1 ? null : data[0][1];
  335.         }
  336.  
  337.         @Override
  338.         public T peek2() {
  339.             return count == 1 ? null : data[1][1];
  340.         }
  341.  
  342.         private T poll(int heapID) {
  343.             if (count == 1) { // empty
  344.                 return null;
  345.             }
  346.             T ret = data[heapID][1];
  347.             int pos2 = links[heapID][1];
  348.  
  349.             count--;
  350.             remove(heapID, 1);
  351.             remove(1 - heapID, pos2);
  352.  
  353.             return ret;
  354.         }
  355.  
  356.         /**
  357.          * removes selected element, count has already been reduced
  358.          *
  359.          * @param heapID
  360.          *            id
  361.          * @param pos
  362.          *            indexed from 1
  363.          */
  364.         private void remove(int heapID, int pos) {
  365.             if (!exists(pos)) {
  366.                 // removed elemenent was last ^_^
  367.                 return;
  368.             }
  369.             swap(heapID, pos, count);
  370.  
  371.             T[] heap = data[heapID];
  372.  
  373.             // see if needs bubbling up
  374.             int parent = parent(pos);
  375.             if (exists(parent)
  376.                     && cs[heapID].compare(heap[pos], heap[parent]) < 0) {
  377.                 bubbleUpAt(heapID, pos);
  378.             } else {
  379.                 bubbleDownAt(heapID, pos);
  380.             }
  381.         }
  382.  
  383.         private void bubbleDownAt(int heapID, int pos) {
  384.             T[] heap = data[heapID];
  385.             int min = pos; // position of minimum
  386.             int left = left(pos);
  387.             int right = right(pos);
  388.             if (exists(left) && cs[heapID].compare(heap[left], heap[min]) < 0) {
  389.                 min = left;
  390.             }
  391.             if (exists(right) && cs[heapID].compare(heap[right], heap[min]) < 0) {
  392.                 min = right;
  393.             }
  394.             if (min != pos) {
  395.                 swap(heapID, min, pos);
  396.                 bubbleDownAt(heapID, min);
  397.             }
  398.         }
  399.  
  400.         @Override
  401.         public T poll1() {
  402.             return poll(0);
  403.         }
  404.  
  405.         @Override
  406.         public T poll2() {
  407.             return poll(1);
  408.         }
  409.  
  410.     }
  411.  
  412.     class Priority2Queue<E> {
  413.         private TreeSet<E> q1;
  414.         private TreeSet<E> q2;
  415.  
  416.         public Priority2Queue(Comparator<? super E> c1, Comparator<? super E> c2) {
  417.             q1 = new TreeSet<E>(c1);
  418.             q2 = new TreeSet<E>(c2);
  419.         }
  420.  
  421.         public void add(E e) {
  422.             q1.add(e);
  423.             q2.add(e);
  424.         }
  425.  
  426.         private E pollx(TreeSet<E> a, TreeSet<E> b) {
  427.             E top = a.first();
  428.             a.remove(top);
  429.             b.remove(top);
  430.             return top;
  431.         }
  432.  
  433.         public E poll1() {
  434.             return pollx(q1, q2);
  435.         }
  436.  
  437.         public E poll2() {
  438.             return pollx(q2, q1);
  439.         }
  440.     }
  441.  
  442. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement