堆排序
小弟初来咋到,面对算法一脸懵逼,希望各位大神能够给予指点,在此谢过。
简单的基于最大堆的优先队列
/**
* Created by Fearless on 2017/3/30.
*/
public class MaxPQ<T extends Comparable<T>> {
private T[] pq;//优先队列;
private int len = 0;//长度
public MaxPQ(int length) {
pq = (T[]) new Comparable[length + 1];
}
public boolean isEmpty() {
return len == 0;
}
public int size() {
return len;
}
public void insert(T v) {
pq[++len] = v;
swim(len);
}
public T delMax() {
T max = pq[1];//索引0处不放数据,所以最大的数据在索引1处
exch(1, len--);//将最大的数据放到最后,且将长度减一
pq[len + 1] = null;//将交换后的最后一个数据的位置置空
sink(1);//恢复堆的有序性
return max;//返回最大值
}
/***
* 自下而上的堆有序化操作
* @param i
*/
private void swim(int i) {
/**
* 1该元素与其父节点中的元素做比较
* 2如果比父节点的元素大交换二者的位置,交换位置后重复步骤1,
* 直到父节点大于等于该节点,或已经是根节点
* pq[i] 的父节点是pq[i/2]
*/
while (i >= 1 && less(i / 2, i)) {
exch(i / 2, i);
i = i / 2;
}
}
/***
* 从上到下的堆有序化操作
* @param i
*/
private void sink(int i) {
/**
* 1该元素与其子节点中的最大元素进行比较
* 2如果比最大的小交换二者的位置,交换位置后重复步骤1,
* 直到没有子节点或比其最大子节点大
* pq[i] 的子节点分别为pq[2*i],pq[2*i+1]
* 选用最大子节点A做比较能够保证父节点B大于A就会大于B的所有子节点,
* 如果B小于A,A与B交换后仍能保证A大于此时的所有子节点
*/
while ((2 * i) <= len) {
int j=2*i;
//如果有两个子节点,且右节点大于左节点,j等于右节点的索引
if(j<len&&less(j,j+1)) j++;
//如果大于最大的子节点,退出循环
if(!less(i,j)) break;
exch(i,j);
i=j;
}
}
/***
* 比较大小
* @param i
* @param j
* @return
*/
private boolean less(int i, int j) {
return pq[i].compareTo(pq[j]) < 0;
}
/***
* 返回大的索引
* @param i
* @param j
* @return
*/
private int max(int i, int j) {
if (pq[i].compareTo(pq[j]) > 0) {
return i;
} else {
return j;
}
}
/***
* 交换元素位置
* @param i
* @param i1
*/
private void exch(int i, int i1) {
T temp = pq[i];
pq[i] = pq[i1];
pq[i1] = temp;
}
}
堆排序
思路:利用最大堆的特点,其堆顶必定是整个堆中的最大值,依次取堆顶值,得到的数据就是有序的
import java.util.Arrays;
/**
* Created by Fearless on 2017/4/7.
*/
public class StackSort {
private static Comparable[] a={5,87,96,44,58,32,25,1,77,69,36,44};//测试数组
public static void main(String ... args){
sort(a);
}
public static void sort(Comparable[] a){
System.out.println(Arrays.toString(a));
int length=a.length;
/*为了方便排序,新建辅助数组,将newA[0] 的位置空出来
*这样就可以通过index/2和index*2、index*2+1 方便的找到父节点和子节点
*/
Comparable[] newA=new Comparable[length+1];
System.arraycopy(a,0,newA,1,length);
for(int i=length/2;i>0;--i){
sink(newA,i,length);
}
int j=0;
while (length>0){
//取当前堆中最大值赋给数组a
a[j++]=newA[1];
//将最大值放到最后一个节点上,并删除最后一个节点
exch(newA,1,length--);
//对剩下的数据进行有序化
sink(newA,1,length);
}
System.out.println("降序:"+Arrays.toString(a));
System.arraycopy(newA,1,a,0,a.length);
System.out.println("升序:"+Arrays.toString(a));
}
/***
* 从上到下有序化堆
* @param a
* @param i
* @param length
*/
private static void sink(Comparable[] a, int i,int length) {
while((i*2)<=length){
int j=i*2;
if(j<length&&less(a[j],a[j+1])) j++;
if(!less(a[i],a[j])) break;
exch(a,i,j);
i=j;
}
}
/***
* 交换i,j位置
* @param a
* @param i
* @param j
*/
private static void exch(Comparable[] a, int i, int j) {
Comparable temp=a[i];
a[i]=a[j];
a[j]=temp;
}
/**
* 比较
* @param i
* @param j
* @return
*/
private static boolean less(Comparable i, Comparable j) {
return i.compareTo(j)<0;
}
}
ps:找不到合适的画图工具,所以没有画出执行过程。。。