Problem desc:
i seem to have a problem with my MIN-heap structure. I get the nullpointer in the min-heapify method in the first if-statement. The test class doesnt matter in this case
Can anyone spot the error? Here is the code for the minHeap (Line 31 is the first IF statement in the minHeapify method):
public class PQHeap implements PQ {
private PriorityQueue pq;
private Element[] heapArray;
private int heapSize;
public PQHeap(int maxElms) {
pq = new PriorityQueue(maxElms);
heapArray = new Element[maxElms];
heapSize = 0;
}
public void minHeapify(int index) {
int left = getLeft(index);
int right = getRight(index);
int smallest = index;
if (left < heapSize && heapArray[left].getKey() < heapArray[index].getKey()) {
smallest = left;
}
if (right < heapSize && heapArray[right].getKey() < heapArray[smallest].getKey()) {
smallest = right;
}
if (smallest != index) {
exchangeKey(heapArray[index].getKey(), heapArray[smallest].getKey());
minHeapify(smallest);
}
}
public int getLeft(int index) {
return index * 2;
}
public int getRight(int index) {
return index * 2 + 1;
}
public int getParent(int index) {
return index / 2;
}
public void exchangeKey(int a, int b) {
int temp = a;
a = b;
b = temp;
}
#Override
public Element extractMin() {
Element min = heapArray[0];
heapArray[0] = heapArray[heapArray.length - 1];
minHeapify(0);
return min;
}
#Override
public void insert(Element e) {
heapSize++;
int i = heapSize;
heapArray[i] = e;
while (i > 1 && heapArray[getParent(i)].getKey() > heapArray[i].getKey()) {
exchangeKey(heapArray[i].getKey(), getParent(heapArray[i].getKey()));
i = getParent(i);
}
}
//SKAL FJERNES
public void print() {
for (int i = 1; i <= heapSize / 2; i++) {
System.out.print(" PARENT : " + heapArray[i].getKey()
+ " LEFT CHILD : " + heapArray[2 * i].getKey()
+ " RIGHT CHILD :" + heapArray[2 * i + 1].getKey());
System.out.println();
}
}
//SKAL FJERNES
public void minHeap() {
for (int pos = (heapSize / 2); pos >= 1; pos--) {
minHeapify(pos);
}
}
}
Related
I have a homework that the teacher test if it's corrects by checking it's output using this website moodle.caseine.org, so to test my code the program execute these lines and compare the output with the expected one, this is the test :
Tas t = new Tas();
Random r = new Random(123);
for(int i =0; i<10000;i++)t.inser(r.nextInt());
for(int i =0;i<10000;i++)System.out.println(t.supprMax());
System.out.println(t);
And my Heap (Tas) class:
package td1;
import java.util.ArrayList;
import java.util.List;
public class Tas {
private List<Integer> t;
public Tas() {
t = new ArrayList<>();
}
public Tas(ArrayList<Integer> tab) {
t = new ArrayList<Integer>(tab);
}
public static int getFilsGauche(int i) {
return 2 * i + 1;
}
public static int getFilsDroit(int i) {
return 2 * i + 2;
}
public static int getParent(int i) {
return (i - 1) / 2;
}
public boolean estVide() {
return t.isEmpty();
}
#Override
public String toString() {
String str = "";
int size = t.size();
if (size > 0) {
str += "[" + t.get(0);
str += toString(0);
str += "]";
}
return str;
}
public boolean testTas() {
int size = t.size();
int check = 0;
if (size > 0) {
for (int i = 0; i < t.size(); i++) {
if (getFilsGauche(i) < size) {
if (t.get(i) < t.get(getFilsGauche(i))) {
check++;
}
}
if (getFilsDroit(i) < size) {
if (t.get(i) < t.get(getFilsDroit(i))) {
check++;
}
}
}
}
return check == 0;
}
public String toString(int i) {
String str = "";
int size = t.size();
if (getFilsGauche(i) < size) {
str += "[";
str += t.get(getFilsGauche(i));
str += toString(getFilsGauche(i));
str += "]";
}
if (getFilsDroit(i) < size) {
str += "[";
str += t.get(getFilsDroit(i));
str += toString(getFilsDroit(i));
str += "]";
}
return str;
}
//insert value and sort
public void inser(int value) {
t.add(value);
int index = t.size() - 1;
if (index > 0) {
inserCheck(index); // O(log n)
}
}
public void inserCheck(int i) {
int temp = 0;
int parent = getParent(i);
if (parent >= 0 && t.get(i) > t.get(parent)) {
temp = t.get(parent);
t.set(parent, t.get(i));
t.set(i, temp);
inserCheck(parent);
}
}
//switch position of last element is list with first (deletes first and return it)
public int supprMax() {
int size = t.size();
int max = 0;
if (size > 0) {
max = t.get(0);
t.set(0, t.get(size - 1));
t.remove(size - 1);
supprMax(0);
}
else {
throw new IllegalStateException();
}
return max;
}
public void supprMax(int i) {
int size = t.size();
int temp = 0;
int index = i;
if (getFilsGauche(i) < size && t.get(getFilsGauche(i)) > t.get(index)) {
index = getFilsGauche(i);
}
if (getFilsDroit(i) < size && t.get(getFilsDroit(i)) > t.get(index)) {
index = getFilsDroit(i);
}
if (index != i) {
temp = t.get(index);
t.set(index, t.get(i));
t.set(i, temp);
supprMax(index);
}
}
public static void tri(int[] tab) {
Tas tas = new Tas();
for (int i = 0; i < tab.length; i++) {
tas.inser(tab[i]);
}
for (int i = 0; i < tab.length; i++) {
tab[i] = tas.supprMax();
}
}
}
The last 3 lines of the test are :
-2145024521
-2147061786
-2145666206
But the last 3 of my code are :
-2145024521
-2145666206
-2147061786
The problem are probably with the inser and supprMax methods.
I hate to get a bad grade just because of 3 lines placement, because it is a program that verify the code, it dosn't care the the solution was close, it's still says it's wrong.
I have generated a minheap to this file but I think something I have missed but I can't identify what are the things I have missed. I have missed something on --private void bubbleDown() { }-- section but I can't find what are the things missed by me.
private int default_size = 100; // how big the heap should be
private T[] array;
private int size;
public Heap() {
#SuppressWarnings("unchecked")
T[] tmp = (T[]) (new Comparable[default_size]);
array = tmp;
size = 0;
}
boolean isRoot(int index) { return (index == 0); }
int leftChild(int index) { return 2 * index + 1; }
int parent(int index) { return (index - 1) / 2; }
int rightChild(int index) { return 2 * index + 2; }
T myParent(int index) { return array[parent(index)]; }
T myLeftChild(int index) { return array[leftChild(index)]; }
T myRightChild(int index) { return array[rightChild(index)]; }
boolean hasLeftChild(int i) { return leftChild(i) < size-1; }
boolean hasRightChild(int i){ return rightChild(i) < size-1; }
private void swap(int a, int b) {
T tmp = array[a];
array[a] = array[b];
array[b] = tmp;
}
public boolean isEmpty() { return (size == 0); }
/* adding heap */
public void add(T value) {
if(size == default_size) throw new IllegalStateException("Full array");
array[size++] = value;
bubbleUp();
}
public void bubbleUp() {
if(size == 0) throw new IllegalStateException("Shape error");
int index = size - 1;
while(!isRoot(index)) {
if(myParent(index).compareTo(array[index]) <= 0) break;
/* else part */
swap(parent(index), index);
index = parent(index);
}
}
/* removing */
public T remove() {
if(isEmpty()) return null;
T res = array[0]; /* root */
array[0] = array[size-1];
size --;
bubbleDown();
return res;
}
// i think this section having wrong something
private void bubbleDown() {
int parent = 0;
int leftChild = 2*parent + 1;
int rightChild = 2*parent + 2;
int choice = compareAndPick(leftChild, rightChild);
while (choice != -1)
{
swap(choice, parent);
parent = choice;
choice = compareAndPick(2*choice+1, 2*choice+2);
}
}
private int compareAndPick(int leftChild, int rightChild)
{
if (leftChild >= default_size || array[leftChild] == null) return -1;
if (array[leftChild].compareTo(array[rightChild]) <= 0 || (array[rightChild] == null))
return leftChild;
return rightChild;
}
public void show() {
for(int i=0; i<size; i++)
System.out.print(array[i] + " ");
System.out.println("=======");
}
public static void main(String [] args) {
Heap<Integer> heap = new Heap<Integer>();
for(int i=0; i<10; i++) {
heap.add((Integer)(int)(Math.random() * 100));
heap.show();
}
System.out.println("You should see sorted numbers");
while(!heap.isEmpty()) {
System.out.print(heap.remove());
System.out.print(" ");
heap.show();
}
System.out.println();
}
}
this code used generics and min heap functions.. i need to identify what is the wrong thing did by me on bubbleDown() section
Explanation
The bubbleDown() method is not a different way to insert a node and move it to it's correct position in the Heap. When bubbleDown() is called it's job is to Heapify the Binary Tree from any state. So your attempt to write the method just by changing the condition from the bubbleUp() method isn't gonna help you.
Extra
Here is a video that can give you the idea of how bubbleDown is supposed to work.
I've made a priority queue implementation that uses heap, but it works somewhat but I've encountered a problem where if I dequeue the priority queue it doesn't heapify correctly.
For example if I input 10 elements from an array ranging from 0 - 9, since this is a MaxHeap implementation it should always return the highest value and then heapify to correct the tree but it doesn't.
When I dequeue and get 9 and I don't get 8 when I dequeue again, I instead get 0 because it swaps from the last index but it doesn't fix the tree.
I've tried debugging and unit testing but I simply can't find where the problem is. I was wondering if some fresh eyes could see what I could not, thanks in advance!
import java.lang.reflect.Array;
public class HeapPriorityQueue<T extends Comparable<? super T>> implements PriorityQueue<T> {
private Class<T> clazz;
private int lastIndex, capacity;
private T heap[];
public HeapPriorityQueue(Class<T> clazz, int capacity) {
this.clazz = clazz;
this.capacity = capacity;
this.heap = (T[]) Array.newInstance(clazz, capacity);
this.lastIndex = -1;
}
#Override
public void clear() {
this.lastIndex = -1;
this.heap = (T[]) Array.newInstance(clazz, capacity);
System.out.println("The queue has been destroyed!");
}
#Override
public boolean isEmpty() {
// TODO Auto-generated method stub
return lastIndex == -1;
}
#Override
public boolean isFull() {
// TODO Auto-generated method stub
return lastIndex == capacity-1;
}
#Override
public int size() {
// TODO Auto-generated method stub
return lastIndex;
}
#Override
public void enqueue(T element) {
if (!isFull()) {
heap[++lastIndex] = element;
shiftUp();
String test = "";
for (int i = 0; i < heap.length; i++) {
test += "" + heap[i] + " ";
}
System.out.println(test);
}
}
#Override
public T dequeue() {
if(isEmpty()) throw new QueueEmptyException();
T rootValue = heap[0];
swap(0, lastIndex);
heap[lastIndex] = null;
lastIndex--;
shiftDown();
String test = "";
for (int i = 0; i < heap.length; i++) {
test += "" + heap[i] + " ";
}
System.out.println(test);
return rootValue;
}
#Override
public T getFront() {
if(isEmpty()) throw new QueueEmptyException();
return heap[0];
}
private void shiftUp() {
int index = lastIndex;
int parentIndex = parent(index);
while (parentIndex > -1 && heap[index].compareTo(heap[parentIndex]) > 0) {
swap(index, parentIndex);
index = parentIndex;
parentIndex = parent(parentIndex);
}
}
private void shiftDown() {
int index = 0;
while (index < lastIndex) {
T maxValue = heap[index];
int maxIndex = index;
int leftIndex = left(index);
if (leftIndex > 0 && maxValue.compareTo(heap[leftIndex]) > 0) {
maxValue = heap[leftIndex];
maxIndex = leftIndex;
}
int rightIndex = left(index);
if (rightIndex > 0 && maxValue.compareTo(heap[rightIndex]) > 0) {
maxValue = heap[rightIndex];
maxIndex = rightIndex;
}
if (maxIndex == index) {
break;
}
swap(maxIndex, index);
index = maxIndex;
}
}
private int parent(int index) {
return index/2;
}
private int left(int index) {
int leftChild = index * 2;
return leftChild;
}
private int right(int index) {
int rightChild = index * 2 + 1;
return rightChild;
}
private void swap(int index1, int index2) {
T temp = heap[index1];
heap[index1] = heap[index2];
heap[index2 ] = temp;
}
public static void main(String[] args) {
Integer[] data = {1, 2, 5, 6, 7, 8, 9, 10, 15, 20};
HeapPriorityQueue<Integer> pq = new HeapPriorityQueue<Integer>(Integer.class,10);
for (Integer i : data) {
pq.enqueue(i);
}
System.out.println(pq.dequeue());
System.out.println(pq.dequeue());
}
}
I have a remove method in a Priority Queue class I created from scratch for an assignment. The priority queue I created is held in an array, with the index starting at 0. I keep track of size which is equal to the arrays length. The remove method uses a helper method entitled:
public int findSmallest(int parent)
where parent is the position in the array that the parent is stored at, and I am looking to return its smallest child. Order is simply the number of children each node that is not a leaf has. The code for my findSmallest:
public int findSmallest(int parent) {
int child = parent * order + 1;
int smallest = child;
for (int i = child; i < order + child; ++i) {
if (size >= i) {
return child;
}
if (queue[i].priority <= queue[smallest].priority) {
smallest = child;
}
}
return child;
}
It is currently an array out of bounds exception
Complete implementation of PriorityQueue Class I created:
import java.util.*;
public class PriorityQueue {
private class Item {
private int priority;
private Object data;
private Item(int p, Object d) {
priority = p;
data = d;
}
}
private Item queue[];
private int order;
private int size;
public PriorityQueue(int ord, int s) {
queue = new Item[s];
order = ord;
size = 0;
}
public int getPriority() {
if (size > 0) {
return queue[0].priority;
}
// -55 signifies that the queue is empty
return -55;
}
public Object getData() {
if (size > 0) {
return queue[0].priority;
}
return null;
}
public void remove() {
if (empty() == true) {
System.out.println("Queue is empty, there is nothing to remove.");
return;
}
Item x = queue[size - 1];
size--;
int child = 1;
int parent = 0;
while (child <= size) {
child = findSmallest(parent);
for (int i = order * parent + 1; i < child + order; i++) {
if (child < size && queue[i].priority < queue[child].priority)
child = i;
}
if (x.priority < queue[child].priority)
break;
else {
parent = child;
queue[(child - 1) / order] = queue[child];
child = order * child + 1;
}
}
queue[(child - 1) / order] = x;
}
public int findSmallest(int parent) {
int child = parent * order + 1;
int smallest = child;
for (int i = child; i < order + child; ++i) {
if (size >= i) {
return child;
}
if (queue[i].priority <= queue[smallest].priority) {
smallest = child;
}
}
return child;
}
public int getSize() {
return size;
}
public boolean full() {
return size == queue.length;
}
public boolean empty() {
if (size > 0) {
return false;
}
return true;
}
public void insert(int p, Object d) {
// 1. Create a new Item and add it to queue[size]
// Somewhere store new node created as TEMP
// 2. while loop
// 3. check if node has parent
// 4. if it does --> check if parent.priority > child.priority
// 5. if yes, swap
if (full() == true) {
System.out.println("Queue is full, cannot add new node.");
return;
}
queue[size] = new Item(p, d);
sort();
size++;
}
// Sort() swaps new child node with parents if child.priority < parent.priority
public void sort() {
int child = size;
Item temp = queue[child];
while ( child > 0 && queue[child].priority < queue[(child-1)/(order)].priority) {
queue[child] = queue[(child-1)/order];
queue[(child-1)/order] = temp;
child = ((child - 1) / order);
}
queue[child] = temp;
}
public static void main(String[] args) {
PriorityQueue p1 = new PriorityQueue(5, 100);
PriorityQueue p2 = new PriorityQueue(6, 100);
PriorityQueue p3 = new PriorityQueue(7, 100);
int p = -1; //pointless initialization to keep the compiler happy
p1.insert(0, new Integer(0));
System.out.println("First insert");
for (int i = 1; i < 100; i++)
p1.insert(i, new Integer(i));
for (int i = 0; i < 100; i++)
p2.insert(i, new Integer(i));
for (int i = 0; i < 100; i++)
p3.insert(i, new Integer(i));
System.out.println("First insert tests");
System.out.print(p1.getPriority()+",");
while (!p1.empty()) {
p = p1.getPriority();
Object d = p1.getData();
p1.remove();
}
System.out.println(p);
System.out.print(p2.getPriority()+",");
while (!p2.empty()) {
p = p2.getPriority();
Object d = p2.getData();
p2.remove();
}
System.out.println(p);
System.out.print(p3.getPriority()+",");
while (!p3.empty()) {
p = p3.getPriority();
Object d = p3.getData();
p3.remove();
}
System.out.println(p);
System.out.println("First Remove Test");
for (int i = 100; i > 0 ; i--)
p1.insert(i, new Integer(i));
for (int i = 100; i > 0 ; i--)
p2.insert(i, new Integer(i));
for (int i = 100; i > 0 ; i--)
p3.insert(i, new Integer(i));
System.out.println("Second insert tests");
System.out.print(p1.getPriority()+",");
while (!p1.empty()) {
p = p1.getPriority();
Object d = p1.getData();
p1.remove();
}
System.out.println(p);
System.out.print(p2.getPriority()+",");
while (!p2.empty()) {
p = p2.getPriority();
Object d = p2.getData();
p2.remove();
}
System.out.println(p);
System.out.print(p3.getPriority()+",");
while (!p3.empty()) {
p = p3.getPriority();
Object d = p3.getData();
p3.remove();
}
System.out.println(p);
System.out.println("Second Remove Test");
Random r1 = new Random(1000);
while (!p3.full()) {
p = r1.nextInt(200);
System.out.print(p+",");
p3.insert(p, new Integer(p));
}
System.out.println();
while (!p3.empty()) {
System.out.print(p3.getPriority()+",");
Object d = p3.getData();
p3.remove();
}
System.out.println();
System.out.println("Third Remove Test");
}
}
Main includes 3 different ways I am testing my code.
If your problem is just with the findSmallest method, here is the solution:
public int findSmallest( int parent ) {
int smallestChild = -1;
int firstChild = parent * order + 1;
int lastChild = parent * order + order;
int currentSmallestChild = firstChild;
for ( int i = firstChild + 1; i <= lastChild; i++ ) {
if ( i > size || queue[i] == null ) {
break;
}
if ( queue[currentSmallestChild].priority > queue[i].priority ) {
currentSmallestChild = i;
smallestChild = i;
}
}
return smallestChild;
}
It will return -1 if there is not a smallest child. This code can be improved, I let it this way because I think it is easier to understand. Let me know if it works.
I have this code for a heap tree and I'm stuck with the iterators.
I need in-order, pre-order and post-order iterators, but I have no idea how to do it.
If someone has an idea or example please help.
class Numbers implements Comparable<Numbers> {
private int value;
public Numbers(int value) {
this.value = value;
}
public String toString() {
return Integer.toString(value);
}
public int getValue() {
return this.value;
}
public int compareTo(Numbers o) {
int tmp = o.getValue();
if (value > tmp)
return 1;
if (value < tmp)
return -1;
return 0;
}
}
class BinaryHeapIsFull extends Exception {
BinaryHeapIsFull() {
super("There is no more place in the heap!");
}
}
public class BinaryHeap<E extends Comparable> {
E[] elements;
int count;
public BinaryHeap(int maxSize) {
elements = (E[]) new Comparable[maxSize];
this.count = 0;
}
public void enqueue(E elem) throws BinaryHeapIsFull {
if (count == elements.length)
throw new BinaryHeapIsFull();
int i = count++;
while (i > 0 && elements[(i - 1) / 2].compareTo(elem) == 1) {
elements[i] = elements[(i - 1) / 2];
i = (i - 1) / 2;
}
elements[i] = elem;
}
public E findMin() {
return elements[0];
}
public E dequeueMin() {
if (count == 0)
return null;
E result = elements[0];
E last = elements[--count];
int i = 0;
while (2 * i + 1 <= count) {
int child = 2 * i + 1;
if (child < count
&& elements[child + 1].compareTo(elements[child]) == -1)
child++;
if (last.compareTo(elements[child]) == -1
|| last.compareTo(elements[child]) == 0)
break;
elements[i] = elements[child];
i = child;
}
elements[i] = last;
return result;
}
public String toString() {
String print = "";
for (int i = 0; i < count; i++)
print += elements[i].toString() + " ";
return print;
}
public void sort() {
int a = count;
for (int i = 0; i < a; i++) {
System.out.print(findMin() + " ");
dequeueMin();
}
}
public static void main(String[] args) throws BinaryHeapIsFull {
BinaryHeap<Numbers> b = new BinaryHeap<Numbers>(10);
b.enqueue(new Numbers(6));
System.out.println(b.toString());
b.enqueue(new Numbers(3));
System.out.println(b.toString());
b.enqueue(new Numbers(4));
System.out.println(b.toString());
b.enqueue(new Numbers(1));
System.out.println(b.toString());
b.enqueue(new Numbers(5));
System.out.println(b.toString());
b.enqueue(new Numbers(0));
System.out.println(b.toString());
b.enqueue(new Numbers(2));
System.out.println(b.toString());
b.dequeueMin();
System.out.println(b.toString());
b.dequeueMin();
System.out.println(b.toString());
System.out.println(b.findMin());
b.sort();
}
}
I'd start with three classes, one for each case, that implements the Iterator interface. Give those iterators an instance of your binary heap and let them do their thing.
public class BinaryHeapPreOrderIterator implements Iterator {
// constructor and methods for Iterator here.
}