学习目标:
目标:熟练运用Java所学知识
学习内容:
本文内容:实现堆,并使用堆模拟优先级队列
模拟思路:
模拟优先级队列首先要明确都需要实现什么功能,本篇文章实现了一下功能
- 首先需要在类中创建两个参数
private int[] arr = new int[100];//用于存储插入的数据
private int size = 0;//记录优先级队列数组中有效元素个数
- 重写toStirng方法,用于打印优先级队列对象
@Override
public String toString() {
//将数组中的有效元素拷贝到新数组并返回
int[] newArr=Arrays.copyOf(arr,size);
return Arrays.toString(newArr);
}
- 使用数组作为参数创建优先级队列,也就是说将数组通过小顶堆的方式进行排序,这里就需要使用到向下调整的方法
//向下调整
public void shiftDown(int[] arr, int index, int size) {
int parent = index;//需要调整的位置
int child = 2 * parent + 1;//chile标记parent的左孩子节点
while (child < size) {
if (child + 1 < size && arr[child] > arr[child + 1]) {
//判断parent左右孩子的大小关系,让child标记较大的孩子节点
child = child + 1;
}
//判断parent和child位置的元素的大小关系,
//如果arr[child] < arr[parent],则交换位置
if (arr[child] < arr[parent]) {
int tmp = arr[child];
arr[child] = arr[parent];
arr[parent] = tmp;
} else {
//否则arr[parent]就已经找到了合适的位置结束循环
break;
}
parent = child;//更新parent标记的位置
child = 2 * parent + 1;//更新child标记的位置,继续下次循环
}
}
//使用数组创建堆(向下调整)
public void creatHeap(int arr[]) {
for (int i = (arr.length - 1 - 1) / 2; i >= 0; i--) {
shiftDown(arr, i, arr.length);
}
this.arr=arr;
size=arr.length;
}
- 向优先级队列中插入元素
//向上调整
public void shiftUp(int[] arr, int size, int index) {
int child = index;//让child标记要调整元素的位置
int parent = (child - 1) / 2;//child位置的父亲位置
while (child > 0) {
//如果arr[child] < arr[parent],则交换位置
if (arr[child] < arr[parent]) {
int temp = arr[child];
arr[child] = arr[parent];
arr[parent] = temp;
} else {
//否则就找到的index位置元素该在的位置
break;
}
child = parent;//更新child位置,进行下次循环
parent = (child - 1) / 2;//更新parent位置,进行下次循环
}
}
//向堆中插入元素
public void offer(int val) {
if (size >= arr.length) {
return;
}
arr[size++] = val;
shiftUp(arr, size, size - 1);
}
- 获取优先级队列中优先级最高的数
//获取堆顶元素
public Integer peek() {
if (size == 0) {
return null;
}
int res = arr[0];
return res;
}
- 删除优先级最高的元素
//删除堆顶元素
public Integer poll() {
if (size == 0) {
return null;
}
int res = arr[0];
//交换操作
int temp = arr[0];
arr[0] = arr[size - 1];
arr[size - 1] = temp;
size--;//堆的有效元素个数减一就实现了删除元素
shiftDown(arr, 0, size);//对堆顶元素进行向下调整
return res;
}
代码汇总:
public class MyPriorityQueue {
private int[] arr = new int[100];//用于存储插入的数据
private int size = 0;//记录数组有效元素个数
//重写toString方法
@Override
public String toString() {
//将数组中的有效元素拷贝到新数组并返回
int[] newArr=Arrays.copyOf(arr,size);
return Arrays.toString(newArr);
}
//向下调整
public void shiftDown(int[] arr, int index, int size) {
int parent = index;//需要调整的位置
int child = 2 * parent + 1;//chile标记parent的左孩子节点
while (child < size) {
if (child + 1 < size && arr[child] > arr[child + 1]) {
//判断parent左右孩子的大小关系,让child标记较小的孩子节点
child = child + 1;
}
//判断parent和child位置的元素的大小关系,
//如果arr[child] < arr[parent],则交换位置
if (arr[child] < arr[parent]) {
int tmp = arr[child];
arr[child] = arr[parent];
arr[parent] = tmp;
} else {
//否则arr[parent]就已经找到了合适的位置结束循环
break;
}
parent = child;//更新parent标记的位置
child = 2 * parent + 1;//更新child标记的位置,继续下次循环
}
}
//向上调整
public void shiftUp(int[] arr, int size, int index) {
int child = index;//让child标记要调整元素的位置
int parent = (child - 1) / 2;//child位置的父亲位置
while (child > 0) {
//如果arr[child] < arr[parent],则交换位置
if (arr[child] < arr[parent]) {
int temp = arr[child];
arr[child] = arr[parent];
arr[parent] = temp;
} else {
//否则就找到的index位置元素该在的位置
break;
}
child = parent;//更新child位置,进行下次循环
parent = (child - 1) / 2;//更新parent位置,进行下次循环
}
}
//使用数组创建堆(向下调整)
public void creatHeap(int newArr[]) {
for(int i:newArr){
arr[size++]=i;
}
for (int i = (size - 1 - 1) / 2; i >= 0; i--) {
shiftDown(arr, i, size);
}
}
//使用数组创建堆(向上调整)
public void creatHeap2(int arr[]) {
for (int x : arr) {
offer(x);
}
}
//向堆中插入元素
public void offer(int val) {
if (size >= arr.length) {
return;
}
arr[size++] = val;
shiftUp(arr, size, size - 1);
}
//获取堆顶元素
public Integer peek() {
if (size == 0) {
return null;
}
int res = arr[0];
return res;
}
//删除堆顶元素
public Integer poll() {
if (size == 0) {
return null;
}
int res = arr[0];
//交换操作
int temp = arr[0];
arr[0] = arr[size - 1];
arr[size - 1] = temp;
size--;//堆的有效元素个数减一就实现了删除元素
shiftDown(arr, 0, size);//对堆顶元素进行向下调整
return res;
}
}
测试用例
public static void main(String[] args) {
MyPriorityQueue m=new MyPriorityQueue();
m.offer(6);//插入元素
m.offer(5);//插入元素
m.offer(4);//插入元素
m.offer(3);//插入元素
int[] arr={9,2,7};
m.creatHeap(arr);//将数组插入到优先级队列中
System.out.println(m.peek());//打印优先级最高的元素
m.poll();//删除优先级最高的元素
System.out.println(m.peek());//运行结果 3
m.poll();//删除优先级最高的元素
System.out.println(m.peek());//运行结果 4
}