优先队列
优先队列实现以下功能:(大根堆)
- insert方法.(插入一个元素)``
- delete方法(删除指定元素)
通过map查找元素在数组中对应的下标删除指定元素,另外使用数组最后一个元素代替这个位置上的元素. - pop方法(删除最大元素(出队))
array[0]删除 - get方法(获取最大元素)
return array[0] - increase方法(增加或减少某个元素的值)
增加可以通过向上过滤完成,减少可以同向下过滤完成 - minVal方法(获取最小元素)
数据结构
//记录数据的数量
private int size;
//记录最小值
private T min;
//存储数据
private T[] array;
//存储对象与其在数组中位置的映射(索引)
private HashMap<T,Integer> indexmap;
流程图
实现
接口
/**
* 优先队列
*/
public interface BaseHeap <T extends HeapObject> {
public void insert(T t) throws NullPointerException;
public void insert(T[] t) throws NullPointerException;
//获取最大元素
public T get();
//最大元素出队
public T pop();
//删除指定元素
public T delete(T t) throws NoSuchObjectException;
//获取最小元素
public T minVal();
//增加或减少元素值
public void increase(T t,int val) throws NoSuchObjectException;
public int size();
}
存储对象
public class HeapObject implements Comparable {
private int data;
private String key;
public HeapObject(){}
public HeapObject(int data,String key){
this.data = data;
this.key = key;
}
public void add(int data){
this.data = this.data+data;
}
@Override
public int compareTo(Object o) {
return data-((HeapObject)o).data;
}
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public String getOnlykey() {
return key;
}
public void setOnlykey(String key) {
this.key = key;
}
}
实现类
insert、delete、increase、update、pop可能会导致最小值改变,需要加条件加以判断更新
upPercolate、downPercolate会导致元素索引的变化,在过滤过程中也要更新indexmap中对应元素的索引
import java.rmi.NoSuchObjectException;
import java.util.HashMap;
//优先队列
public class BinaryHeap <T extends HeapObject> implements BaseHeap<T>{
private static final int DEFAULTSIZE = 10;
private int size;
private T min;
private T[] array;
//store index of object in array
private HashMap<T,Integer> indexmap;
public BinaryHeap(){
this(DEFAULTSIZE);
}
public BinaryHeap(T[] ts){
this(ts.length*2);
this.size = ts.length;
T min = ts[0];
for(int i=0;i<ts.length;i++){
array[i] = ts[i];
//find min
if(ts[i].compareTo(min)<0)
min = ts[i];
}
for(int i=ts.length-1;i>=0;i--)
downPercolate(i);
//find min of index
this.min = min;
}
private BinaryHeap(int size){
array =(T[]) new HeapObject[size];
indexmap = new HashMap<>(size,10);
min = null;
this.size = 0;
}
@Override
public void insert(T t) throws NullPointerException{
if(null == t)
throw new NullPointerException("tar is null");
int index;
//resize
if(this.size==array.length){
T[] old = array;
array = (T[])new HeapObject[old.length*2];
//extend size of array
System.arraycopy(old,0,array,0,old.length);
}
Integer exist = indexmap.get(t);
if(exist==null){
array[index = size++] = t;
this.upPercolate(index);
}else{
//如果堆中已存在对象,更新对象
updateVal(exist);
//更新最小值
min = min==t ?min: foreachfindmin() ;
return;
}
//min of index
if(min==null)
min = array[0];
if(min!=null && min!=t &&t.compareTo(min)<0)
min = t;
}
@Override
public void insert(T[] t) {
for(int i=0;i<t.length;i++)
insert(t[i]);
}
public T get() {
if (array == null || size == 0)
throw new NullPointerException("there is no record");
return array[0];
}
@Override
public T delete(T t) throws NoSuchObjectException{
Integer index = indexmap.get(t);
if(index==null)
throw new NoSuchObjectException("指定对象不存在");
T tar = array[index];
indexmap.remove(tar);
if(size==1){
min = null;
array[--size] = null;
return tar;
}
array[index] = array[--size] ;
updateVal(index);
min = min == tar ? foreachfindmin() : min ;
return tar;
}
//提升对象的优先级
@Override
public void increase(T t,int val) throws NoSuchObjectException{
Integer index = indexmap.get(t);
if(index==null)
throw new NoSuchObjectException("指定对象不存在");
t.add(val);
if (val>0){
upPercolate(index);
min = t == min ? foreachfindmin() : min;
} else if(val<0){
downPercolate(index);
//1.降低min权值 2.降低任意对象权值.
min = t.getData()<min.getData() ? t : min;
}
else
;
}
//更新对象权值,并平衡堆
private void updateVal(int index){
T tar = array[index];
int re = tar.compareTo(array[(index-1)/2]);
if(re>0)
upPercolate(index);
else
downPercolate(index);
}
//遍历查找最小值
private T foreachfindmin(){
int begin = (size-2)/2 + 1;
int end = size-1;
T t = array[begin];
for(int i=begin;i<=end;i++)
if(array[i].compareTo(t)<0)
t=array[i];
return t;
}
//出队
@Override
public T pop() {
if(this.size==0)
return null;
T re = array[0];
indexmap.remove(re);
if(this.size==1){
array[--size] = null;
min = null;
}else{
array[0]=array[--size];
min = size==0 ? null : min;
downPercolate(0);
}
return re;
}
@Override
public int size() {
return this.size;
}
@Override
public T minVal() {
return min;
}
//上浮,并更新map中对象索引
private void upPercolate(int index){
int hole = index;
T t = array[index];
while((hole-1)/2>0
&& t.compareTo(array[(hole-1)/2])>0){
array[hole] = array[(hole-1)/2];
indexmap.put(array[hole],hole);
hole = (hole-1)/2;
}
if(array[0].compareTo(t)<0){
array[hole] = array[0];
indexmap.put(array[hole],hole);
array[hole=0] = t;
}else {
array[hole] = t;
}
indexmap.put(array[hole],hole);
}
//下沉,并更新map中的索引
private void downPercolate(int index){
int hole = index;
int i;
T temp = array[index];
while((hole*2+1)<this.size){
i = hole*2+1;
if(i+1<this.size && array[i+1].compareTo(array[i])>0)
i++;
if(temp.compareTo(array[i])>0)
break;
array[hole] = array[i];
indexmap.put(array[hole],hole);
hole = i;
}
array[hole] = temp;
indexmap.put(array[hole],hole);
}
}
测试
public static void main(String[] args) throws Exception{
BaseHeap heap = new BinaryHeap();
Map<String,HeapObject> map = new HashMap<>();
HeapObject obj = null;
for(int i=0;i<10;i++){
obj = new HeapObject(i,String.valueOf(i));
map.put(String.valueOf(i),obj);
heap.insert(obj);
}
System.out.println("最大值:"+heap.pop().getData());
heap.increase(map.get(String.valueOf(0)),100);
System.out.println("某元素增加100后最大值:"+heap.pop().getData());
System.out.println("最小值:"+heap.minVal().getData());
heap.increase(map.get(String.valueOf(8)),-100);
System.out.println("某元素减少100后最小值:"+heap.minVal().getData());
System.out.print("依次出队: ");
while(heap.size()!=0)
System.out.print(heap.pop().getData()+" ");
}