堆排序

堆排序

小弟初来咋到,面对算法一脸懵逼,希望各位大神能够给予指点,在此谢过。

简单的基于最大堆的优先队列
/**
 * 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:找不到合适的画图工具,所以没有画出执行过程。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值