堆排序
public static void getBigHeap(int[] arr){
for(int i=0;i<arr.length;i++){
heapInsert(arr,i);
}
}
/**
* 获取一个随机数组
* @param maxLength
* @param maxValue
* @return
*/
public static int[] getRandomArr(int maxLength,int maxValue){
int len=(int)(Math.random()*maxLength)+2;
int[] arr=new int[len];
for(int i=0;i<len;i++){
arr[i]=(int)(Math.random()*maxValue);
}
return arr;
}
/**
* 传入一个大根堆数组,其中最后一个index是未进入大根堆的
* 我们目标就是将 新增的数据放在数组最后一个,然后逐渐与自己的父节点进行比较
* 到最后满足大根堆
* @param arr
* @param index
*/
public static void heapInsert(int[] arr ,int index){
while(arr[(index-1)/2]<arr[index]){
swap(arr,(index-1)/2,index);
index=(index-1)/2;
}
}
/**
* 检查某一个节点的后续节点是否符合大根堆,不符合则进行调整
* 向下进行调整
* @param arr
* @param heapSize
*/
public static void heapIfy(int[] arr,int index,int heapSize){
int left= index*2+1;
while(left<heapSize){
int largest=left+1<heapSize&&arr[left+1]>arr[left]?left+1:left;
largest=arr[largest]>arr[index]?largest:index;
if(index==largest){
break;
}
swap(arr,largest,index);
index=largest;
left=index*2+1;
}
}
public static void swap(int[] arr,int a,int b){
int temp=arr[a];
arr[a]=arr[b];
arr[b]=temp;
}
加强堆
/**
* 加强堆。增加了反向索引表
*
* 小根堆
*/
public class HeapGreater<T> {
//存放堆的数组
private ArrayList<T> heap;
//反向索引表
private HashMap<T,Integer> indexMap;
//堆大小
private int heapSize;
//比较器
private Comparator<? super T> comp;
//初始化这个加强堆
public HeapGreater(Comparator<T> c){
this.comp=c;
indexMap=new HashMap<>();
heapSize=0;
heap=new ArrayList<>();
}
public boolean isEmpty(){
return this.heapSize==0;
}
public int size(){
return this.heapSize;
}
public boolean contains(T obj){
return indexMap.containsKey(obj);
}
public T peek(){
return heap.get(0);
}
public void push(T obj){
heap.add(obj);
indexMap.put(obj,heapSize);
heapInsert(heapSize++);
}
public T pop(){
T ans=heap.get(0);
swap(0,heapSize-1); //将头移动到尾部
indexMap.remove(ans);
heap.remove(--heapSize);
heapify(0); //从头开始重新调整堆的位置
return ans;
}
//移除堆上的任意一个节点
public void remove(T obj){
T replace=heap.get(heapSize-1);
int index=indexMap.get(obj);
indexMap.remove(obj);
heap.remove(--heapSize);
if(obj!=replace){
heap.set(index,replace);
indexMap.put(replace,index);
resign(replace);
}
}
/**
* 对指定的堆节点进行堆调整
* @param obj
*/
public void resign(T obj){
heapInsert(indexMap.get(obj));
heapify(indexMap.get(obj));
}
/**
* 返回所有元素
* @return
*/
public List<T> returnAllElements(){
ArrayList<T> ts = new ArrayList<>();
for(T t: heap){
ts.add(t);
}
return ts;
}
/**
* 堆中最后一个元素加入到堆中
* @param index
*/
public void heapInsert(int index){
while(comp.compare(heap.get(index),heap.get((index-1)/2))<0){
swap(index,(index-1)/2);
index=(index-1)/2;
}
}
/**
* 调整指定位置的元素,使之堆化
* @param index
*/
public void heapify(int index){
int left=index*2+1;
while(left<heapSize){
int best=left+1<heapSize&&comp.compare(heap.get(left+1),heap.get(left))<0?(left+1):left;
best=comp.compare(heap.get(best),heap.get(index))<0?best:index;
if(best==index){
break;
}
swap(best,index);
index=best;
left=index*2+1;
}
}
/**
* 交换
* @param i
* @param j
*/
public void swap(int i,int j){
T o1=heap.get(i);
T o2=heap.get(j);
heap.set(i,o2);
heap.set(j,o1);
indexMap.put(o2,i);
indexMap.put(o1,j);
}
}
两种堆中最重要的是3个方法
heapify
,heapInsert
,swap