Heap based priority queue implementation - java

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());
}
}

Related

BubbleDown function(min heap) not working

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.

How does one replace last element of full stack with new element? (java)

public class ourStack1 {
private int elements[];
private int index; // indicate the next position to put a new data
private int size;
public ourStack1() {
elements = new int[10];
index = 0;
size = 0;
}
public void push(int value) {
if(size == 10) {
System.out.println("Stack is full, no push");
return;
}
elements[index] = value;
++index;
++size;
}
public int pop() {
if(size == 0) {
System.out.println("Stack is empty, no pop");
return -1;
}
int temp = elements[index - 1];
--index;
--size;
return temp;
}
public int peek() {
if(size == 0) {
System.out.println("Stack is empty, no peek");
return -1;
}
return elements[index - 1];
}
/*
public int mySize() {
// you know how to do this
}
*/
public static void main(String[] args) {
ourStack1 x = new ourStack1();
for(int i = 0; i < 10; ++i)
x.push(i);
for(int i = 0; i < 10; ++i)
System.out.println(x.pop());
}
}
I'm confused on how to overwrite the last element added to the full stack. I want to add element to replace the last element while not exceeding the array size[10]
public void replaceLast(int value) {
if (this.size > 0) {
this.pop();
}
this.push(value);
}

Minheapify method

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);
}
}
}

CircularArrayQueue implementation Java

I am trying to implement a CircularArrayQueue. I've been given a JUnit test which my queue must pass.I suppose I am doing something wrong with the front and rear pointers. How should i approach learning data structures and algorithms ?
import java.util.NoSuchElementException;
public class CircularArrayQueue implements MyQueue {
private Integer[] array;
// initial size of the array
private int N;
private int front;
private int rear;
public CircularArrayQueue() {
this.N = 10;
array = new Integer[N];
front = rear = 0;
}
public CircularArrayQueue(int size) {
this.N = size;
array = new Integer[N];
front = rear = 0;
}
// enqueues an element at the rear of the queue
// if the queue is already full it is resized, doubling its size
#Override
public void enqueue(int in) {
if (rear == N) {
if (front == 0) {
resize();
array[rear] = in;
rear++;
} else {
array[rear] = in;
rear = 0;
}
} else {
array[rear] = in;
rear++;
}
}
public void resize() {
Integer[] temp = new Integer[array.length * 2];
for (int i = 0; i < array.length; i++) {
temp[i] = array[i];
}
temp = array;
}
// dequeues an element
// if the queue is empty a NoSuchElement Exception is thrown
#Override
public int dequeue() throws NoSuchElementException {
if (isEmpty()) {
throw new NoSuchElementException("The queue is full");
}
int headElement = array[front];
if (front == N) {
array[front] = null;
front = 0;
} else {
array[front] = null;
front++;
}
return headElement;
}
#Override
public int noItems() {
return N - getCapacityLeft();
}
#Override
public boolean isEmpty() {
return (getCapacityLeft() == N);
}
// return the number of indexes that are empty
public int getCapacityLeft() {
return (N - rear + front) % N;
}
}
Your initialization is absolutely fine, and we do start with:
front = rear = 0;
Befor adding an item to the Q, we modify rear as
rear = (rear + 1) % N;
The % allows us to maintain the circular property of the queue. Also you must be wondering that if we modify rear before adding any item, then 0 index is left empty, well we have to compromise here with one array item being left blank, in order to have correct implementations for checking of isEmpty() and isFull() functions:
That said, the correct code for isEmpty() is:
#Override
public boolean isEmpty()
{
return front == rear;
}
You should also have a function isFull() like:
#Override
public boolean isFull()
{
return front == ((rear + 1) % N);
}
Also the line temp = array; in your resize() should be array = temp; and you must also update the value of N after calling resize().
Hence, the correct code is:
import java.util.NoSuchElementException;
public class CircularArrayQueue implements MyQueue
{
private Integer[] array;
//initial size of the array
private int N;
private int front;
private int rear;
private int count = 0;//total number of items currently in queue.
public CircularArrayQueue()
{
this.N = 10;
array = new Integer[N];
front = rear = 0;
}
public CircularArrayQueue(int size)
{
this.N = size;
array = new Integer[N];
front = rear = 0;
}
//enqueues an element at the rear of the queue
// if the queue is already full it is resized, doubling its size
#Override
public void enqueue(int in)
{
count++;
if (isFull())
{
resize();
rear = (rear + 1) % N;
array[rear] = in;
}
else
{
rear = (rear + 1) % N;
array[rear] = in;
}
}
public void resize()
{
Integer[] temp = new Integer[array.length*2];
N = array.length*2;
for(int i=0; i<array.length; i++)
{
temp[i] = array[i];
}
array = temp;
}
//dequeues an element
// if the queue is empty a NoSuchElement Exception is thrown
#Override
public int dequeue() throws NoSuchElementException
{
if(isEmpty())
{
throw new Exception("The queue is empty");
}
front = (front + 1) % N;
int headElement = array[front];
count--;
return headElement;
}
#Override
public int noItems()
{
return count;
}
#Override
public boolean isEmpty()
{
return front == rear;
}
#Override
public boolean isFull()
{
return front == ((rear + 1) % N);
}
//return the number of indexes that are empty
public int getCapacityLeft()
{
return N - 1 - count;
}
}

Problem in implementing Sorted List by Array in Java

There seems to be a problem in add method of the class I have written.. I want to make a SortedList using an array, but I can't figure out what the problem is. This is my code:
public class SortedList {
private Integer[] elements;
private int size;
private int capacity;
public SortedList(int cap) {
elements = new Integer[cap];
if (cap > 0)
{
cap = capacity;
}
else
capacity = 10;
}
public boolean isEmpty()
{
return size == 0;
}
public boolean isFull()
{
return size == capacity;
}
public int size()
{
return size;
}
public void doubleCapacity()
{
capacity = capacity * 2;
}
public void add(Integer el)
{
if(this.isEmpty())
{
elements[0] = el;
size++;
}
else if(this.isFull())
{
this.doubleCapacity();
for(int i = 0; i<this.size(); i++)
{
if(el >= elements[i])
{
elements[i+2] = elements[i+1];
elements[i+1] = el;
}
else
{
elements[i+1] = elements[i];
elements[i] = el;
}
}
size++;
}
else
{
for(int i = 0; i<this.size(); i++)
{
if(el >= elements[i])
{
elements[i+2] = elements[i+1];
elements[i+1] = el;
}
else
{
elements[i+1] = elements[i];
elements[i] = el;
}
}
size++;
}
}
public String toString()
{
String s = "";
s = s + "<SortedList[";
for(int i = 0; i < this.size(); i++)
{
s = s + elements[i];
if(i < this.size()-1)
s = s + ",";
}
s = s + "]>";
return s;
}
public static void main(String[] args)
{
SortedList sl = new SortedList(5);
sl.add(3);
//sl.add(2);
sl.add(4);
sl.add(5);
// sl.add(6);
System.out.println(sl.toString());
}
}
My code works if I only add 2 Integers to my list, but when I try to add the numbers 3,4,5 then I get 3,5,5...
What can be the problem? Thanks..
public class SortedList {
private Integer[] elements;
private int size=0;
private int capacity;
public SortedList(int cap) {
elements = new Integer[cap];
if (cap > 0)
{
capacity = cap;
}
else
capacity = 10;
}
public boolean isEmpty()
{
return size == 0;
}
public boolean isFull()
{
return size == capacity;
}
public int size()
{
return size;
}
public void doubleCapacity()
{
capacity = capacity * 2;
}
public void add(Integer el) throws Exception{
elements[size] = el;
size++;
if(size>capacity){
throw new Exception("Size Exceeded");
}
}
public String toString()
{
sort();
String s = "";
s = s + "<SortedList[";
for(int i = 0; i < this.size(); i++)
{
s = s + elements[i];
if(i < this.size()-1)
s = s + ",";
}
s = s + "]>";
return s;
}
public void sort(){
for (int i=0; i <size()-1; i++) {
if (elements[i] > elements[i+1]) {
// exchange elements
int temp = elements[i];
elements[i] = elements[i+1];
elements[i+1] = temp;
}
}
}
public static void main(String[] args)
{
try {
SortedList sl = new SortedList(5);
sl.add(3);
//sl.add(2);
sl.add(6);
sl.add(5);
// sl.add(6);
System.out.println(sl.toString());
} catch (Exception ex) {
Logger.getLogger(SortedList.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Your insertion code doesn't work.
elements[i+1] = elements[i];
elements[i] = el;
What happens to the old value of elements[i+1]?
I'd recommend the following changes to the previous solution. If you're only calling sort in toString(), your list is going to get out of order quickly in cases where you have multiple unsorted elements in a row (Now you could remove sort() from toString()). It's essentially a quick insertion sort that dies as soon as it can't make any more swaps down the list. Again, as dty suggested, a faster choice would be a binary search to find the insertion point.
public void doubleCapacity(){
capacity = capacity * 2;
Integer temp[] = new Integer[capacity];
for (int i = 0; i < size; i++){
temp[i] = elements[i];
}
elements = temp;
}
public void add(Integer el){
if(size+1>capacity){
doubleCapacity();
}
elements[size] = el;
size++;
sort();
}
public void sort(){
//Iterates down the list until it's sorted.
for (int i=size()-2; i >= 0 && (elements[i] < elements[i+1]); i--) {
// exchange elements
int temp = elements[i];
elements[i] = elements[i+1];
elements[i+1] = temp;
}
}

Categories

Resources