BAEL-4409 : codes have been added (#10925)
* BAEL-4409 : codes have been added * BAEL-4409 : how to implement min-max heap in java * BAEL-4409 : how to implement min-max heap in java
This commit is contained in:
parent
51ceab1ac3
commit
dd715d4e70
@ -0,0 +1,344 @@
|
|||||||
|
package com.baeldung.minmaxheap;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by arash on 15.06.21.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MinMaxHeap<T extends Comparable<T>> {
|
||||||
|
private List<T> array;
|
||||||
|
private int capacity;
|
||||||
|
private int indicator;
|
||||||
|
|
||||||
|
MinMaxHeap(int capacity) {
|
||||||
|
array = new ArrayList<>();
|
||||||
|
this.capacity = capacity;
|
||||||
|
indicator = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
MinMaxHeap(List<T> array) {
|
||||||
|
this.array = array;
|
||||||
|
this.capacity = array.size();
|
||||||
|
this.indicator = array.size() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> getMinMaxHeap() {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> create() {
|
||||||
|
for (int i = Math.floorDiv(array.size(), 2); i >= 1; i--) {
|
||||||
|
pushDown(array, i);
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushDown(List<T> array, int i) {
|
||||||
|
if (isEvenLevel(i)) {
|
||||||
|
pushDownMin(array, i);
|
||||||
|
} else {
|
||||||
|
pushDownMax(array, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushDownMin(List<T> h, int i) {
|
||||||
|
while (getLeftChildIndex(i) < indicator) {
|
||||||
|
int indexOfSmallest = getIndexOfSmallestChildOrGrandChild(h, i);
|
||||||
|
if (h.get(indexOfSmallest - 1).compareTo(h.get(i - 1)) < 0) {
|
||||||
|
if (getParentIndex(getParentIndex(indexOfSmallest)) == i) {
|
||||||
|
if (h.get(indexOfSmallest - 1).compareTo(h.get(i - 1)) < 0) {
|
||||||
|
swap(indexOfSmallest - 1, i - 1, h);
|
||||||
|
if (h.get(indexOfSmallest - 1).compareTo(h.get(getParentIndex(indexOfSmallest) - 1)) > 0) {
|
||||||
|
swap(indexOfSmallest - 1, getParentIndex(indexOfSmallest) - 1, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (h.get(indexOfSmallest - 1).compareTo(h.get(i - 1)) < 0) {
|
||||||
|
swap(indexOfSmallest - 1, i - 1, h);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i = indexOfSmallest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushDownMax(List<T> h, int i) {
|
||||||
|
while (getLeftChildIndex(i) < indicator) {
|
||||||
|
int indexOfGreatest = getIndexOfGreatestChildOrGrandChild(h, i);
|
||||||
|
if (h.get(indexOfGreatest - 1).compareTo(h.get(i - 1)) > 0) {
|
||||||
|
if (getParentIndex(getParentIndex(indexOfGreatest)) == i) {
|
||||||
|
if (h.get(indexOfGreatest - 1).compareTo(h.get(i - 1)) > 0) {
|
||||||
|
swap(indexOfGreatest - 1, i - 1, h);
|
||||||
|
if (h.get(indexOfGreatest - 1).compareTo(h.get(getParentIndex(indexOfGreatest) - 1)) < 0) {
|
||||||
|
swap(indexOfGreatest - 1, getParentIndex(indexOfGreatest) - 1, h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (h.get(indexOfGreatest - 1).compareTo(h.get(i - 1)) > 0) {
|
||||||
|
swap(indexOfGreatest - 1, i - 1, h);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i = indexOfGreatest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void swap(int i, int j, List<T> h) { //switch data at x with data at y
|
||||||
|
T temp = h.get(i);
|
||||||
|
h.set(i, h.get(j));
|
||||||
|
h.set(j, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getLeftChildIndex(int i) {
|
||||||
|
return 2 * i;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getRightChildIndex(int i) {
|
||||||
|
return ((2 * i) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getParentIndex(int i) {
|
||||||
|
return i / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getGrandparentIndex(int i) {
|
||||||
|
return i / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEvenLevel(int i) {
|
||||||
|
return logBase2(i) % 2 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int logBase2(int num) {
|
||||||
|
return (int) (Math.log(num) / Math.log(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMinChildIndex(int i) {
|
||||||
|
return array.get(getLeftChildIndex(i)).compareTo(array.get(getRightChildIndex(i))) < 0 ? getLeftChildIndex(i) : getRightChildIndex(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMaxChildIndex(int i) {
|
||||||
|
return array.get(getLeftChildIndex(i)).compareTo(array.get(getRightChildIndex(i))) > 0 ? getLeftChildIndex(i) : getRightChildIndex(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIndexOfSmallestChildOrGrandChild(List<T> h, int i) {
|
||||||
|
int minIndex = getLeftChildIndex(i);
|
||||||
|
T minValue = h.get(minIndex - 1);
|
||||||
|
|
||||||
|
if (getRightChildIndex(i) < indicator) {
|
||||||
|
if (h.get(getRightChildIndex(i) - 1).compareTo(minValue) < 0) {
|
||||||
|
minValue = h.get(getRightChildIndex(i));
|
||||||
|
minIndex = getRightChildIndex(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return minIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getLeftChildIndex(getLeftChildIndex(i)) < indicator) {
|
||||||
|
if (h.get(getLeftChildIndex(getLeftChildIndex(i)) - 1).compareTo(minValue) < 0) {
|
||||||
|
minValue = h.get(getLeftChildIndex(getLeftChildIndex(i)) - 1);
|
||||||
|
minIndex = getLeftChildIndex(getLeftChildIndex(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return minIndex; //if no leftmost grandchild
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getRightChildIndex(getLeftChildIndex(i)) < indicator) {
|
||||||
|
if (h.get(getRightChildIndex(getLeftChildIndex(i)) - 1).compareTo(minValue) < 0) {
|
||||||
|
minValue = h.get(getRightChildIndex(getLeftChildIndex(i)) - 1);
|
||||||
|
minIndex = getRightChildIndex(getLeftChildIndex(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return minIndex; //if no left-right grandchild
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getLeftChildIndex(getRightChildIndex(i)) < indicator) {
|
||||||
|
if (h.get(getLeftChildIndex(getRightChildIndex(i)) - 1).compareTo(minValue) < 0) {
|
||||||
|
minValue = h.get(getLeftChildIndex(getRightChildIndex(i)) - 1);
|
||||||
|
minIndex = getLeftChildIndex(getRightChildIndex(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return minIndex; //if no right-left grandchild
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getRightChildIndex(getRightChildIndex(i)) < indicator) {
|
||||||
|
if (h.get(getRightChildIndex(getRightChildIndex(i)) - 1).compareTo(minValue) < 0) {
|
||||||
|
minValue = h.get(getRightChildIndex(getRightChildIndex(i)) - 1);
|
||||||
|
minIndex = getRightChildIndex(getRightChildIndex(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return minIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return minIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIndexOfGreatestChildOrGrandChild(List<T> h, int i) {
|
||||||
|
int maxIndex = getLeftChildIndex(i); //we know left child exists
|
||||||
|
T maxValue = h.get(maxIndex - 1);
|
||||||
|
|
||||||
|
if (getRightChildIndex(i) < indicator) {
|
||||||
|
if (h.get(getRightChildIndex(i) - 1).compareTo(maxValue) > 0) {
|
||||||
|
maxValue = h.get(getRightChildIndex(i) - 1);
|
||||||
|
maxIndex = getRightChildIndex(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return maxIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getLeftChildIndex(getLeftChildIndex(i)) < indicator) {
|
||||||
|
if (h.get(getLeftChildIndex(getLeftChildIndex(i)) - 1).compareTo(maxValue) > 0) {
|
||||||
|
maxValue = h.get(getLeftChildIndex(getLeftChildIndex(i)) - 1);
|
||||||
|
maxIndex = getLeftChildIndex(getLeftChildIndex(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return maxIndex; //if no leftmost grandchild
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getRightChildIndex(getLeftChildIndex(i)) < indicator) {
|
||||||
|
if (h.get(getRightChildIndex(getLeftChildIndex(i)) - 1).compareTo(maxValue) > 0) {
|
||||||
|
maxValue = h.get(getRightChildIndex(getLeftChildIndex(i)) - 1);
|
||||||
|
maxIndex = getRightChildIndex(getLeftChildIndex(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return maxIndex; //if no left-right grandchild
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getLeftChildIndex(getRightChildIndex(i)) < indicator) {
|
||||||
|
if (h.get(getLeftChildIndex(getRightChildIndex(i)) - 1).compareTo(maxValue) > 0) {
|
||||||
|
maxValue = h.get(getLeftChildIndex(getRightChildIndex(i)) - 1);
|
||||||
|
maxIndex = getLeftChildIndex(getRightChildIndex(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return maxIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getRightChildIndex(getRightChildIndex(i)) < indicator) {
|
||||||
|
if (h.get(getRightChildIndex(getRightChildIndex(i)) - 1).compareTo(maxValue) > 0) {
|
||||||
|
maxValue = h.get(getRightChildIndex(getRightChildIndex(i)) - 1);
|
||||||
|
maxIndex = getRightChildIndex(getRightChildIndex(i));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return maxIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public boolean isFull() {
|
||||||
|
return indicator == this.capacity + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return indicator == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert(T item) {
|
||||||
|
if (isEmpty()) {
|
||||||
|
array.add(item);
|
||||||
|
indicator++;
|
||||||
|
} else if (!isFull()) {
|
||||||
|
array.add(item);
|
||||||
|
pushUp(array, indicator);
|
||||||
|
indicator++;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("invalid operation !!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushUpMin(List<T> h, int i) {
|
||||||
|
while (hasGrandparent(i) && h.get(i - 1).compareTo(h.get(getGrandparentIndex(i) - 1)) < 0) {
|
||||||
|
swap(i - 1, getGrandparentIndex(i) - 1, h);
|
||||||
|
i = getGrandparentIndex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushUpMax(List<T> h, int i) {
|
||||||
|
while (hasGrandparent(i) && h.get(i - 1).compareTo(h.get(getGrandparentIndex(i) - 1)) > 0) {
|
||||||
|
swap(i - 1, getGrandparentIndex(i) - 1, h);
|
||||||
|
i = getGrandparentIndex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasGrandparent(int i) {
|
||||||
|
return getParentIndex(i) > 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void pushUp(List<T> h, int i) {
|
||||||
|
if (i != 1) {
|
||||||
|
if (isEvenLevel(i)) {
|
||||||
|
if (h.get(i - 1).compareTo(h.get(getParentIndex(i) - 1)) < 0) {
|
||||||
|
pushUpMin(h, i);
|
||||||
|
} else {
|
||||||
|
swap(i - 1, getParentIndex(i) - 1, h);
|
||||||
|
i = getParentIndex(i);
|
||||||
|
pushUpMax(h, i);
|
||||||
|
}
|
||||||
|
} else if (h.get(i - 1).compareTo(h.get(getParentIndex(i) - 1)) > 0) {
|
||||||
|
pushUpMax(h, i);
|
||||||
|
} else {
|
||||||
|
swap(i - 1, getParentIndex(i) - 1, h);
|
||||||
|
i = getParentIndex(i);
|
||||||
|
pushUpMin(h, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public T min() {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
return array.get(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T max() {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
if (indicator == 2) {
|
||||||
|
return array.get(0);
|
||||||
|
}
|
||||||
|
if (indicator == 3) {
|
||||||
|
return array.get(1);
|
||||||
|
}
|
||||||
|
return array.get(1).compareTo(array.get(2)) < 0 ? array.get(2) : array.get(1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T removeMin() {
|
||||||
|
T min = min();
|
||||||
|
if (min != null) {
|
||||||
|
if (indicator == 2) {
|
||||||
|
array.remove(indicator--);
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
array.set(0, array.get(--indicator - 1));
|
||||||
|
array.remove(indicator - 1);
|
||||||
|
pushDown(array, 1);
|
||||||
|
}
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T removeMax() {
|
||||||
|
T max = max();
|
||||||
|
if (max != null) {
|
||||||
|
int maxIndex;
|
||||||
|
if (indicator == 2) {
|
||||||
|
maxIndex = 0;
|
||||||
|
array.remove(--indicator - 1);
|
||||||
|
return max;
|
||||||
|
} else if (indicator == 3) {
|
||||||
|
maxIndex = 1;
|
||||||
|
array.remove(--indicator - 1);
|
||||||
|
return max;
|
||||||
|
} else {
|
||||||
|
maxIndex = array.get(1).compareTo(array.get(2)) < 0 ? 2 : 1;
|
||||||
|
}
|
||||||
|
array.set(maxIndex, array.get(--indicator - 1));
|
||||||
|
array.remove(indicator - 1);
|
||||||
|
pushDown(array, maxIndex + 1);
|
||||||
|
}
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.baeldung.minmaxheap;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
public class MinMaxHeapUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenUnOrderedArray_WhenCreateMinMaxHeap_ThenIsEqualWithMinMaxHeapOrdered() {
|
||||||
|
List<Integer> list = Arrays.asList(34, 12, 28, 9, 30, 19, 1, 40);
|
||||||
|
MinMaxHeap<Integer> minMaxHeap = new MinMaxHeap<>(list);
|
||||||
|
minMaxHeap.create();
|
||||||
|
Assert.assertEquals(Arrays.asList(1, 40, 34, 9, 30, 19, 28, 12), list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNewElement_WhenInserted_ThenIsEqualWithMinMaxHeapOrdered() {
|
||||||
|
MinMaxHeap<Integer> minMaxHeap = new MinMaxHeap(8);
|
||||||
|
minMaxHeap.insert(34);
|
||||||
|
minMaxHeap.insert(12);
|
||||||
|
minMaxHeap.insert(28);
|
||||||
|
minMaxHeap.insert(9);
|
||||||
|
minMaxHeap.insert(30);
|
||||||
|
minMaxHeap.insert(19);
|
||||||
|
minMaxHeap.insert(1);
|
||||||
|
minMaxHeap.insert(40);
|
||||||
|
Assert.assertEquals(Arrays.asList(1, 40, 28, 12, 30, 19, 9, 34), minMaxHeap.getMinMaxHeap());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user