package com.williamfiset.algorithms.datastructures.priorityqueue; import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.PriorityQueue; import org.junit.*; public class BinaryHeapQuickRemovalsTest { static final int LOOPS = 100; static final int MAX_SZ = 100; @Before public void setup() {} @Test public void testEmpty() { BinaryHeapQuickRemovals<Integer> q = new BinaryHeapQuickRemovals<>(); assertEquals(q.size(), 0); assertTrue(q.isEmpty()); assertEquals(q.poll(), null); assertEquals(q.peek(), null); } @Test public void testHeapProperty() { BinaryHeapQuickRemovals<Integer> q = new BinaryHeapQuickRemovals<>(); Integer[] nums = {3, 2, 5, 6, 7, 9, 4, 8, 1}; // Try manually creating heap for (int n : nums) q.add(n); for (int i = 1; i <= 9; i++) assertTrue(i == q.poll()); q.clear(); // Try heapify constructor q = new BinaryHeapQuickRemovals<>(nums); for (int i = 1; i <= 9; i++) assertTrue(i == q.poll()); } @Test public void testHeapify() { for (int i = 1; i < LOOPS; i++) { Integer[] lst = genRandArray(i); BinaryHeapQuickRemovals<Integer> pq = new BinaryHeapQuickRemovals<>(lst); PriorityQueue<Integer> pq2 = new PriorityQueue<>(i); for (int x : lst) pq2.add(x); assertTrue(pq.isMinHeap(0)); while (!pq2.isEmpty()) { assertEquals(pq.poll(), pq2.poll()); } } } @Test public void testClear() { BinaryHeapQuickRemovals<String> q; String[] strs = {"aa", "bb", "cc", "dd", "ee"}; q = new BinaryHeapQuickRemovals<>(strs); q.clear(); assertEquals(q.size(), 0); assertTrue(q.isEmpty()); } @Test public void testContainment() { String[] strs = {"aa", "bb", "cc", "dd", "ee"}; BinaryHeapQuickRemovals<String> q = new BinaryHeapQuickRemovals<>(strs); q.remove("aa"); assertFalse(q.contains("aa")); q.remove("bb"); assertFalse(q.contains("bb")); q.remove("cc"); assertFalse(q.contains("cc")); q.remove("dd"); assertFalse(q.contains("dd")); q.clear(); assertFalse(q.contains("ee")); } @Test public void testContainmentRandomized() { for (int i = 0; i < LOOPS; i++) { List<Integer> randNums = genRandList(100); PriorityQueue<Integer> PQ = new PriorityQueue<>(); BinaryHeapQuickRemovals<Integer> pq = new BinaryHeapQuickRemovals<>(); for (int j = 0; j < randNums.size(); j++) { pq.add(randNums.get(j)); PQ.add(randNums.get(j)); } for (int j = 0; j < randNums.size(); j++) { int randVal = randNums.get(j); assertEquals(pq.contains(randVal), PQ.contains(randVal)); pq.remove(randVal); PQ.remove(randVal); assertEquals(pq.contains(randVal), PQ.contains(randVal)); } } } public void sequentialRemoving(Integer[] in, Integer[] removeOrder) { assertEquals(in.length, removeOrder.length); BinaryHeapQuickRemovals<Integer> pq = new BinaryHeapQuickRemovals<>(in); PriorityQueue<Integer> PQ = new PriorityQueue<>(); for (int value : in) PQ.offer(value); assertTrue(pq.isMinHeap(0)); for (int i = 0; i < removeOrder.length; i++) { int elem = removeOrder[i]; assertTrue(pq.peek() == PQ.peek()); assertEquals(pq.remove(elem), PQ.remove(elem)); assertTrue(pq.size() == PQ.size()); assertTrue(pq.isMinHeap(0)); } assertTrue(pq.isEmpty()); } @Test public void testRemoving() { Integer[] in = {1, 2, 3, 4, 5, 6, 7}; Integer[] removeOrder = {1, 3, 6, 4, 5, 7, 2}; sequentialRemoving(in, removeOrder); in = new Integer[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; removeOrder = new Integer[] {7, 4, 6, 10, 2, 5, 11, 3, 1, 8, 9}; sequentialRemoving(in, removeOrder); in = new Integer[] {8, 1, 3, 3, 5, 3}; removeOrder = new Integer[] {3, 3, 5, 8, 1, 3}; sequentialRemoving(in, removeOrder); in = new Integer[] {7, 7, 3, 1, 1, 2}; removeOrder = new Integer[] {2, 7, 1, 3, 7, 1}; sequentialRemoving(in, removeOrder); in = new Integer[] {32, 66, 93, 42, 41, 91, 54, 64, 9, 35}; removeOrder = new Integer[] {64, 93, 54, 41, 35, 9, 66, 42, 32, 91}; sequentialRemoving(in, removeOrder); } @Test public void testRemovingDuplicates() { Integer[] in = new Integer[] {2, 7, 2, 11, 7, 13, 2}; BinaryHeapQuickRemovals<Integer> pq = new BinaryHeapQuickRemovals<>(in); assertTrue(pq.peek() == 2); pq.add(3); assertTrue(pq.poll() == 2); assertTrue(pq.poll() == 2); assertTrue(pq.poll() == 2); assertTrue(pq.poll() == 3); assertTrue(pq.poll() == 7); assertTrue(pq.poll() == 7); assertTrue(pq.poll() == 11); assertTrue(pq.poll() == 13); } @Test public void testRandomizedPolling() { for (int i = 0; i < LOOPS; i++) { int sz = i; List<Integer> randNums = genRandList(sz); PriorityQueue<Integer> pq1 = new PriorityQueue<>(); BinaryHeapQuickRemovals<Integer> pq2 = new BinaryHeapQuickRemovals<>(); // Add all the elements to both priority queues for (Integer value : randNums) { pq1.offer(value); pq2.add(value); } while (!pq1.isEmpty()) { assertTrue(pq2.isMinHeap(0)); assertEquals(pq1.size(), pq2.size()); assertEquals(pq1.peek(), pq2.peek()); assertEquals(pq1.contains(pq1.peek()), pq2.contains(pq2.peek())); Integer v1 = pq1.poll(); Integer v2 = pq2.poll(); assertEquals(v1, v2); assertEquals(pq1.peek(), pq2.peek()); assertEquals(pq1.size(), pq2.size()); assertTrue(pq2.isMinHeap(0)); } } } @Test public void testRandomizedRemoving() { for (int i = 0; i < LOOPS; i++) { int sz = i; List<Integer> randNums = genRandList(sz); PriorityQueue<Integer> pq1 = new PriorityQueue<>(); BinaryHeapQuickRemovals<Integer> pq2 = new BinaryHeapQuickRemovals<>(); // Add all the elements to both priority queues for (Integer value : randNums) { pq1.offer(value); pq2.add(value); } Collections.shuffle(randNums); int index = 0; while (!pq1.isEmpty()) { int removeNum = randNums.get(index++); assertTrue(pq2.isMinHeap(0)); assertEquals(pq1.size(), pq2.size()); assertEquals(pq1.peek(), pq2.peek()); pq1.remove(removeNum); pq2.remove(removeNum); assertEquals(pq1.peek(), pq2.peek()); assertEquals(pq1.size(), pq2.size()); assertTrue(pq2.isMinHeap(0)); } } } @Test public void testPQReusability() { List<Integer> SZs = genUniqueRandList(LOOPS); PriorityQueue<Integer> PQ = new PriorityQueue<>(); BinaryHeapQuickRemovals<Integer> pq = new BinaryHeapQuickRemovals<>(); for (int sz : SZs) { pq.clear(); PQ.clear(); List<Integer> nums = genRandList(sz); for (int n : nums) { pq.add(n); PQ.add(n); } Collections.shuffle(nums); for (int i = 0; i < sz / 2; i++) { // Sometimes add a new number into the BinaryHeapQuickRemovals if (0.25 < Math.random()) { int randNum = (int) (Math.random() * 10000); PQ.add(randNum); pq.add(randNum); } int removeNum = nums.get(i); assertTrue(pq.isMinHeap(0)); assertEquals(PQ.size(), pq.size()); assertEquals(PQ.peek(), pq.peek()); PQ.remove(removeNum); pq.remove(removeNum); assertEquals(PQ.peek(), pq.peek()); assertEquals(PQ.size(), pq.size()); assertTrue(pq.isMinHeap(0)); } } } static Integer[] genRandArray(int sz) { Integer[] lst = new Integer[sz]; for (int i = 0; i < sz; i++) lst[i] = (int) (Math.random() * MAX_SZ); return lst; } // Generate a list of random numbers static List<Integer> genRandList(int sz) { List<Integer> lst = new ArrayList<>(sz); for (int i = 0; i < sz; i++) lst.add((int) (Math.random() * MAX_SZ)); return lst; } // Generate a list of unique random numbers static List<Integer> genUniqueRandList(int sz) { List<Integer> lst = new ArrayList<>(sz); for (int i = 0; i < sz; i++) lst.add(i); Collections.shuffle(lst); return lst; } }