堆和优先队列


  • 在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 基于数组实现的最大堆(没有实现接口)上浮、下沉函数
package org.yanan.堆和优先队列;

import org.yanan.data.ArrayList;
//基于数组实现的最大堆
public class MaxHeap<E extends Comparable<E>> {
   //1.定义成员变量和构造函数
   private ArrayList<E> data;
   public MaxHeap(){
   	data=new ArrayList<>();
   }
   public MaxHeap(int capacity){//创建指定容量大小的最大堆
   	data=new ArrayList<>(capacity);
   }
   //2.将任意数组整理成最大堆:从最后一个非叶结点开始寻找
   public MaxHeap(E[] arr){
   	data=new ArrayList<>(arr);
   	//从最后一个元素的父节点开始
   	for(int i=parent(data.getSize()-1);i>=0;i--){
   		siftDown(i);
   	}
   }
   //3.返回堆中元素的个数
   public int size(){
   	return data.getSize();
   }
   //4.判断堆中是否为空
   public boolean isEmpty(){
   	//return data.getSize()==0;
   	return data.isEmpty();
   }
   //5.提供三个辅助函数:一个索引的父节点的索引,左孩子的索引,右孩子的索引
   private int parent(int index){//当前结点的角标
   	if(index==0){//根节点无父节点
   		throw new IllegalArgumentException("none parent");
   	}
   	return (index-1)/2;
   }
   private int leftChild(int index){//左孩子
   	return 2*index+1;
   }
   private int rightChild(int index){//右孩子
   	return 2*index+2;
   }
   //6.向堆中添加元素:默认添加在数组最后,即堆的最末尾,然后进行上浮操作
   public void add(E e){
   	data.addLast(e);//默认将添加的元素放到数组的尾部
   	siftUp(data.getSize()-1);//然后进行上浮操作
   }
   //6.1:上浮操作
   private void siftUp(int index) {//上浮,得到要上浮元素的下标
   	while(index>0&&data.get(parent(index)).compareTo(data.get(index))<0){
   		//如果是根则无父节点,上浮的前提是当前的值大于父节点值
   		data.swap(index, parent(index));
   		index=parent(index);
   	}
   }
   //7.查看堆中最大元素
   public E findMax(){
   	if(data.isEmpty()){
   		throw new IllegalArgumentException("堆为空");
   	}
   	return data.getFirst();
   }
   //8.删除堆中最大元素:最大堆的最大值在堆顶,下标为0,和最后一个元素交换位置,直接删除最后一个元素,然后堆顶元素下沉
   public E extractMax(){
   	E e=findMax();
   	data.swap(0, data.getSize()-1);
   	data.removeLast();
   	siftDown(0);
   	return e;
   }
   //8.1:下沉操作 ,主要是堆顶元素和左右孩子比较
   private void siftDown(int index) {
   	//先判断右孩子是否存在;然后判断左右孩子的大小,最后判断父节点与左右还子的大小
   	while(leftChild(index)<data.getSize()){//只有左孩子的下标不越界,右孩子才有可能存在
   		int k=leftChild(index);//左孩子的下标
   		if(k+1<data.getSize()&&data.get(k+1).compareTo(data.get(k))>0){
   			k=rightChild(index);
   		}
   		//比较index和k的大小
   		if(data.get(index).compareTo(data.get(k))<0){
   			data.swap(index, k);
   		}else{
   			break;
   		}
   	}
   }
   //9.替换最大值,取出最大值,放入一个新元素
   public E replace(E e){
   	E res=findMax();
   	data.set(0, e);
   	siftDown(0);
   	return res;
   }
   public void clear() {
   	data.clear();
   }
}
  • 优先队列
    普通队列:先进先出,后进后出
    优先队列:出队顺序和入队顺序无关,和优先级相关,本质还是队列

    应用: 任务管理器中:动态选择优先级最高的任务执行
    游戏中:塔防优先攻击(距离,威胁,先后)
    优先队列的经典问题
    在1000000000个元素中选出前100名?
    在N个元素中选出前M个元素 排序?

nlogm 使用优先队列,维护当前看到的前m个元素,最小堆(大小是相对的)

  • 基于最大堆实现的优先队列
package org.yanan.堆和优先队列;

import org.yanan.data.Queue;

public class PriorityQueue<E extends Comparable<E>> implements Queue<E>{
	private MaxHeap<E> heap;
	public PriorityQueue(){
		heap=new MaxHeap<>();
	}
	@Override
	public int getSize() {
		return heap.size();
	}
	@Override
	public boolean isEmpty() {
		return heap.isEmpty();
	}
	@Override
	public void enqueue(E e) {
		heap.add(e);
	}
	@Override
	public E dequeue() {
		return heap.extractMax();
	}
	@Override
	public E getFront() {
		return heap.findMax();
	}
	@Override
	public E getRear() {
		return null;
	}
	@Override
	public void clear() {
		heap.clear();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值