优先级队列
如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。这样,我们就引入了优先级队列 这种数据结构。 优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有查找、插入一个新元素、删除。一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。
优先级队列是基于最小堆原理实现。最小堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于其左子节点和右子节的值。完全最小堆的示意图如下:
代码实现
public class PriorityQueue {
private int[] data;
private int maxSize = 100;
private int curSize = 0;
public PriorityQueue(){
data = new int[maxSize];
}
/**
* 向上调整(除最后一个节点,其他节点有序)
*/
private void FilterUp(int[] arr,int end){
int j = end, i = (end-1) / 2;
int tmp = arr[j];
while (j > 0){
if(arr[i] <= tmp) break;
arr[j] = arr[i];
j = i; i = (j-1) / 2;
}
arr[j] = tmp;
}
/**
* 向下调整(根节点的数值大),调整为最小堆
*/
private void FilterDown(int[] arr,int begin,int end){
int i = begin, j = i * 2 + 1;
int tmp = arr[i];
while (j <= end){
if(j+1 <= end && arr[j] > arr[j+1]) ++j;
if(tmp <= arr[j]) break;
arr[i] = arr[j];
i = j; j = i * 2 + 1;
}
arr[i] = tmp;
}
public int getSize(){
return curSize;
}
public boolean isEmpty(){
return curSize == 0;
}
public void push(int value){
data[curSize] = value;
FilterUp(data,curSize);
curSize++;
}
public int front(){
return data[0];
}
public void pop(){
data[0] = data[curSize-1];
curSize--;
FilterDown(data,0,curSize-1);
}
}
测试用例:
public static void main(String[] args) {
int[] arr = {34,23,34,78,90,89,34,12,100,56,67};
PriorityQueue test = new PriorityQueue();
for(int i = 0;i < arr.length;++i){
test.push(arr[i]);
}
while (!test.isEmpty()){
int x = test.front();
test.pop();
System.out.println(x);
}
}
输出结果:
优先级队列的应用
堆排序
可以用优先级队列,堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。
代码实现:
public class HeapSort {
/**
* 向下调整(根节点的数值大),调整为最小堆
*/
public static void FilterDown(int[] arr,int begin,int end){
int i = begin, j = i * 2 + 1;
int tmp = arr[i];
while (j <= end){
if(j+1 <= end && arr[j] > arr[j+1]) ++j;
if(tmp <= arr[j]) break;
arr[i] = arr[j];
i = j; j = i * 2 + 1;
}
arr[i] = tmp;
}
public static void HeapSort(int[] arr){
if(arr == null || arr.length == 1) return;
int end = arr.length - 1;
int pos = (end-1) / 2;
while (pos >= 0){
FilterDown(arr,pos,end);
--pos;
}
for(int i = end;i > 0;--i){
int tmp = arr[0];
arr[0] = arr[i];
arr[i] = tmp;
FilterDown(arr,0,i-1);
}
}
public static void main(String[] args) {
int[] arr = {34,23,34,78,90,89,34,12,100,56,67};
System.out.println(Arrays.toString(arr));
HeapSort(arr);
System.out.println(Arrays.toString(arr));
}
}