算法数据结构:堆 (java实现)

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);
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值