优先级队列:
优先级队列以数组形式存储数据,以树形形式组织元素的。
在以树形形式组织的时候,默认为小根堆形式。
小根堆:每一个父节点都小于它的左右节点。
在树中:
- 已知子节点,求父节点的公式为:(n-1)/2
- 已知父节点:
①求左孩子:2n+1
②求右孩子:2n+2
思路:
自定义一个类,属性为存放元素的数组和存放元素的下标,
- 添加元素
添加元素时,往树的最后一个添加,然后在从下往上将整个树重新调整成小根堆。
向上调整:判断当前添加的值和父节点的大小,如果父节点大,交换值。然后继续以当前位置为孩子,判读当前位置和其父节点的大小,如果父节点大,交换,依次向上判断,直到判断到根节点。如果父节点小于当前孩子,则说明已经满足小根堆的要求,则直接结束。 - 删除元素
把最后一个元素放入根节点的位置,进行覆盖,然后将最后一个节点进行置空,有助于GC进行回收,最后从上向下重新调整成为小根堆。
向下调整:从根节点开始,判断根节点和左右孩子的最小值的大小,如果根节点小,则满足小根堆,否则,交换根节点和左后孩子的最小值,依次向下判断。
代码:
class PriorityQueue {
int[] array; //存放元素的数组
int size;//存放元素的下标
public PriorityQueue() {
this(10);
}
public PriorityQueue(int s) {
this.array = new int[s];
this.size = 0;
}
public boolean add(int val) { //插入:往最后一个插入. 插入的和父节点比较,比父小,调整
if (size == 0) {
array[size++] = val;
} else {
array[size] = val;//先插入再调整为小根堆
adjustUp(size, val);
}
return true;
}
private void adjustUp(int index,int value){ //从下往上调整
while (index > 0) {
int parent = (index - 1) >>> 1; //已知子求父
if (this.array[parent] <= value) { //父节点小于value,满足小根堆直接跳出
break;
}
//父节点大于value
this.array[index] = this.array[parent];
index = parent; //更新Index的值,继续判断父节点
}
this.array[index] = value;
size++;
}
public boolean remove(){
if(size == 0) {
System.out.println("无元素!");
return false;
}
if(size == 1){
size--;
System.out.println("删除成功");
}
if(size>1) {
array[0] = array[size - 1]; //将最后一个元素放入根节点(覆盖根节点)
adjustDown(0); //从上向下调整为小根堆
} return true;
}
private void adjustDown(int index) { //从上往下调,从根节点开始
//已知根节点,判断根节点和左右子的大小
int tmp = array[index];
int leftChild = index * 2 + 1; // 左节点
for (int i = leftChild; i <= size-1 ; i = 2*i+1) { //进入for循环,说明有左孩子, i的步进是为了寻找下一个左右孩子,进行下一步左右孩子大小的判断
//判断是否有孩子,如果有,找到左右的最小值
if(i < size-1 && array[i] > array[i+1]){ //右孩子小,更新i的值
i++;
}
if(array[i] < tmp) { //小的数赋给根节点
array[index] = array[i];
index = i;
}else {
break;
}
}
array[index] = tmp;
size--;
}
public void show(){
for (int i = 0; i < size ; i++) {
System.out.print(array[i]+" ");
}
System.out.println();
}
}
public class QueueSmallDemo305 {
public static void main(String[] args) {
PriorityQueue priorityQueue = new PriorityQueue();
priorityQueue.add(1);
priorityQueue.add(3);
priorityQueue.add(6);
priorityQueue.add(2);
priorityQueue.add(8);
priorityQueue.add(4);
priorityQueue.show(); //1 2 4 3 8 6
priorityQueue.remove();
priorityQueue.remove();
priorityQueue.show();
}
}
实现结果:
它的小根堆树形表示出来为: