java中的堆是可以用PriorityQueue实现的
而堆在贪心算法中是一种很重要的数据结构,因为它能够实现一个记录中位数的数据结构,而贪心算法本质山是对于不同策略下收益大小的比较,记录最大、最小、中位数(都可以用堆实现)非常有意义。
那么,废话少说,我们先通过一道简单的求中位数的数据结构来回忆一下java中PriorityQueue的实现方法
题目来自左神的ppt
import java.util.PriorityQueue;
import java.util.function.BiFunction;
import java.util.Comparator;
public class MedianHolder {
public static class bigEndComapraotr implements Comparator<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
}
public static double getMedian(int[] test) {
PriorityQueue<Integer> bigEnd = new PriorityQueue<>(new bigEndComapraotr());
//小根堆
PriorityQueue<Integer> smallEnd = new PriorityQueue<>();
double median = -1;
for (int i : test) {
/*
* 尚未初始化,则优先进入大根堆
*/
//System.out.println("进入的数字是 "+i);
if (bigEnd.size()==0&&smallEnd.size()==0) {
//System.out.println(i+"进入大根堆");
bigEnd.add(i);
}
/*
* 若是大于等于大根堆最大值,进入小根堆
*/
else if (bigEnd.peek()<=i) {
//System.out.println(i+"进入小根堆");
smallEnd.add(i);
}
else{
//System.out.println(i+"进入大根堆");
bigEnd.add(i);
}
/*
* 调整使得两边平衡
*/
if (bigEnd.size()-smallEnd.size()>=2) {
int temp1 =bigEnd.poll();
//System.out.println(temp1+"离开大根堆,进入小根堆");
smallEnd.add(temp1);
}
else if (smallEnd.size()-bigEnd.size()>=2) {
int temp2 =smallEnd.poll();
//System.out.println(temp2+"离开小根堆,进入大根堆");
bigEnd.add(temp2);
}
}
/*
* 判断分大根堆和小跟堆后是那种情况:
* 1.大根堆多一个,那么大根堆里面的堆头就是中位数
* 2.大根堆和小根堆一样多,那么大根堆和小根堆数之和的平均数就是中位数
* 3.小根堆多一个,那么小根堆里面的堆头就是中位数
*/
if (bigEnd.size()-smallEnd.size()==1) {
//System.out.println(1);
median = bigEnd.peek();
}
else if (bigEnd.size()-smallEnd.size()==0) {
//System.out.println(bigEnd.peek()+" "+smallEnd.peek());
median = (bigEnd.peek()+smallEnd.peek())/2.0;
}
else if (smallEnd.size()-bigEnd.size()==1) {
//System.out.println(-1);
median = smallEnd.peek();
}
return median;
}
public static void main(String[] args) {
//测试数据
int[] test1 = {1,17,5,27,8,6};
int[] test2 = {2,5,98,12,13};
double median1, median2;
median1 = getMedian(test1);
median2 =getMedian(test2);
//System.out.println(smallEnd.peek()+" "+bigEnd.peek());
System.out.println("数组{1,17,5,27,8,6}的中位数为:"+median1+":预估结果为7");
System.out.println("数组{2,5,98,12,13}的中位数为:"+median2+":预估结果为12");
}
}
运行结果如下
下面是一道典型的哈夫曼树问题,我们可以看出PQ很擅长解决这种问题(省去了排序的麻烦)
import java.security.Principal;
import java.util.PriorityQueue;
public class GreedyPQ {
public static void main(String[] args) {
// TODO Auto-generated method stub
PriorityQueue<Integer> halfman = new PriorityQueue<Integer>();
for(int i=1;i<4;i++)
{
halfman.add(i*10);
}
int sum =0;
while(halfman.size()>=2)
{
int temp1 = halfman.poll();
int temp2 = halfman.poll();
int temp_sum = temp1+temp2;
sum+=temp_sum;
halfman.add(temp_sum);
}
System.out.println("最小花费为:"+sum);
}
}