mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-11 22:22:21 +08:00
Improve priority queues with max-heap (#3648)
This commit is contained in:
@ -1,5 +1,8 @@
|
|||||||
package com.thealgorithms.datastructures.queues;
|
package com.thealgorithms.datastructures.queues;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements a PriorityQueue.
|
* This class implements a PriorityQueue.
|
||||||
*
|
*
|
||||||
@ -8,6 +11,8 @@ package com.thealgorithms.datastructures.queues;
|
|||||||
* most important elements are placed at the front/on the top. In this example I
|
* most important elements are placed at the front/on the top. In this example I
|
||||||
* give numbers that are bigger, a higher priority. Queues in theory have no
|
* give numbers that are bigger, a higher priority. Queues in theory have no
|
||||||
* fixed size but when using an array implementation it does.
|
* fixed size but when using an array implementation it does.
|
||||||
|
* <p>
|
||||||
|
* Additional contibutions made by: PuneetTri(https://github.com/PuneetTri)
|
||||||
*/
|
*/
|
||||||
class PriorityQueue {
|
class PriorityQueue {
|
||||||
|
|
||||||
@ -25,42 +30,113 @@ class PriorityQueue {
|
|||||||
private int nItems;
|
private int nItems;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Default Constructor
|
||||||
|
*/
|
||||||
|
|
||||||
|
public PriorityQueue() {
|
||||||
|
/* If capacity is not defined, default size of 11 would be used
|
||||||
|
* capacity=max+1 because we cant access 0th element of PQ, and to
|
||||||
|
* accomodate (max)th elements we need capacity to be max+1.
|
||||||
|
* Parent is at position k, child at position (k*2,k*2+1), if we
|
||||||
|
* use position 0 in our queue, its child would be at:
|
||||||
|
* (0*2, 0*2+1) -> (0,0). This is why we start at position 1
|
||||||
|
*/
|
||||||
|
int size = 11; // Default value of 11
|
||||||
|
maxSize = size + 1;
|
||||||
|
queueArray = new int[maxSize];
|
||||||
|
nItems = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameterized Constructor
|
||||||
*
|
*
|
||||||
* @param size Size of the queue
|
* @param size Size of the queue
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public PriorityQueue(int size) {
|
public PriorityQueue(int size) {
|
||||||
maxSize = size;
|
maxSize = size + 1;
|
||||||
queueArray = new int[size];
|
queueArray = new int[maxSize];
|
||||||
nItems = 0;
|
nItems = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for the max-heap implementation of PQ
|
||||||
|
* Function would help demote parent node to their correct
|
||||||
|
* position
|
||||||
|
*
|
||||||
|
* @param pos Position of newly added element at bottom
|
||||||
|
*/
|
||||||
|
private void swim(int pos) {
|
||||||
|
// Check if parent is smaller than child node
|
||||||
|
while (pos > 1 && (queueArray[pos / 2] < queueArray[pos])) {
|
||||||
|
// In such case swap value of child with parent
|
||||||
|
int temp = queueArray[pos];
|
||||||
|
queueArray[pos] = queueArray[pos / 2];
|
||||||
|
queueArray[pos / 2] = temp;
|
||||||
|
pos = pos / 2; // Jump to position of parent node
|
||||||
|
}
|
||||||
|
// Promotion of child node will go on until it becomes smaller than the parent
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for the max-heap implementation of PQ
|
||||||
|
* Function would help demote parent node to their correct
|
||||||
|
* position
|
||||||
|
*
|
||||||
|
* @param pos Position of element at top
|
||||||
|
*/
|
||||||
|
private void sink(int pos) {
|
||||||
|
// Check if node's position is that of parent node
|
||||||
|
while (2 * pos <= nItems) {
|
||||||
|
int current = 2 * pos; // Jump to the positon of child node
|
||||||
|
// Compare both the children for the greater one
|
||||||
|
if (current < nItems && queueArray[current] < queueArray[current + 1]) current++;
|
||||||
|
// If the parent node is greater, sink operation is complete. Break the loop
|
||||||
|
if (queueArray[pos] >= queueArray[current]) break;
|
||||||
|
|
||||||
|
// If not exchange the value of parent with child
|
||||||
|
int temp = queueArray[pos];
|
||||||
|
queueArray[pos] = queueArray[current];
|
||||||
|
queueArray[current] = temp;
|
||||||
|
pos = current; // Exchange parent position to child position in the array
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts an element in it's appropriate place
|
* Inserts an element in it's appropriate place
|
||||||
*
|
*
|
||||||
* @param value Value to be inserted
|
* @param value Value to be inserted
|
||||||
*/
|
*/
|
||||||
public void insert(int value) {
|
public void insert(int value) {
|
||||||
|
// Print overflow message if the capacity is full
|
||||||
if (isFull()) {
|
if (isFull()) {
|
||||||
throw new RuntimeException("Queue is full");
|
throw new RuntimeException("Queue is full");
|
||||||
} else {
|
} else {
|
||||||
int j = nItems - 1; // index of last element
|
queueArray[++nItems] = value;
|
||||||
while (j >= 0 && queueArray[j] > value) {
|
swim(nItems); // Swim up the element to its correct position
|
||||||
queueArray[j + 1] = queueArray[j]; // Shifts every element up to make room for insertion
|
|
||||||
j--;
|
|
||||||
}
|
|
||||||
queueArray[j + 1] = value; // Once the correct position is found the value is inserted
|
|
||||||
nItems++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the element from the front of the queue
|
* Dequeue the element with the max priority from PQ
|
||||||
*
|
*
|
||||||
* @return The element removed
|
* @return The element removed
|
||||||
*/
|
*/
|
||||||
public int remove() {
|
public int remove() {
|
||||||
return queueArray[--nItems];
|
if (isEmpty()) {
|
||||||
|
throw new RuntimeException("Queue is Empty");
|
||||||
|
} else {
|
||||||
|
int max = queueArray[1]; // By defintion of our max-heap, value at queueArray[1] pos is the greatest
|
||||||
|
|
||||||
|
// Swap max and last element
|
||||||
|
int temp = queueArray[1];
|
||||||
|
queueArray[1] = queueArray[nItems];
|
||||||
|
queueArray[nItems] = temp;
|
||||||
|
queueArray[nItems--] = 0; // Nullify the last element from the priority queue
|
||||||
|
sink(1); // Sink the element in order
|
||||||
|
|
||||||
|
return max;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -69,7 +145,7 @@ class PriorityQueue {
|
|||||||
* @return element at the front of the queue
|
* @return element at the front of the queue
|
||||||
*/
|
*/
|
||||||
public int peek() {
|
public int peek() {
|
||||||
return queueArray[nItems - 1];
|
return queueArray[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,7 +163,7 @@ class PriorityQueue {
|
|||||||
* @return true if the queue is full
|
* @return true if the queue is full
|
||||||
*/
|
*/
|
||||||
public boolean isFull() {
|
public boolean isFull() {
|
||||||
return (nItems == maxSize);
|
return (nItems == maxSize - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -100,29 +176,3 @@ class PriorityQueue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This class implements the PriorityQueue class above.
|
|
||||||
*
|
|
||||||
* @author Unknown
|
|
||||||
*/
|
|
||||||
public class PriorityQueues {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main method
|
|
||||||
*
|
|
||||||
* @param args Command Line Arguments
|
|
||||||
*/
|
|
||||||
public static void main(String[] args) {
|
|
||||||
PriorityQueue myQueue = new PriorityQueue(4);
|
|
||||||
myQueue.insert(10);
|
|
||||||
myQueue.insert(2);
|
|
||||||
myQueue.insert(5);
|
|
||||||
myQueue.insert(3);
|
|
||||||
// [2, 3, 5, 10] Here higher numbers have higher priority, so they are on the top
|
|
||||||
|
|
||||||
for (int i = 3; i >= 0; i--) {
|
|
||||||
System.out.print(myQueue.remove() + " "); // will print the queue in reverse order [10, 5, 3, 2]
|
|
||||||
}
|
|
||||||
// As you can see, a Priority Queue can be used as a sorting algotithm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user