堆排序及其应用

介绍堆排序及其应用,topk问题,优先级队列等。
优先队列:
优先队列有两个基本的操作:
1、删除最大元素
2、插入新的元素
优先队列的应用场景很多,比如用于定时任务的调度,我们有一个定时任务的调度序列,现在新加入了一个新的定时任务,需要把它放到队列中合适的位置,实际上就是优先级队列的使用。另外,还有在图搜索算法,数据压缩上面的应用。
下面是一个优先队列的API及其实现

public class MaxPQ <Key extends Comparable<Key>> {
    private Key[] pq;
    private int N=0;
    //0位置不放置元素
    MaxPQ(int max){
        pq=(Key[]) new Comparable[max+1];
    }
    void insert(Key v){
        //调整数组大小 为原先的2倍
        if(N+1==pq.length){
            resize(2*pq.length);
        }
        pq[++N]=v;
        swim(N);
    }

    Key max(){
        return pq[1];
    }

    Key delMax(){
        Key max=pq[1];
        swap(1,N--);
        sink(1);
        pq[N+1]=null;
        if(N>0 && N+1==pq.length/4){
            resize(pq.length/2);
        }
        return max;
    }

    boolean isEmpty(){
        return N==0;
    }

    int size(){
        return N;
    }

    private void swim(int k){
        while(k>1 && less(k/2,k)){
            swap(k/2,k);
            k=k/2;
        }
    }
    private void sink(int k){
        while(2*k<=N){
            int j=2*k;
            if(j+1<=N && less(j,j+1)){
                j++;
            }
            if(less(k,j)){
                swap(k,j);
                //向下移动
                k=j;
            }else {
                break;
            }
        }
    }
    private void swap(int i,int j){
        Key a=pq[i];
        pq[i]=pq[j];
        pq[j]=a;
    }

    private boolean less(int i,int j){
        return pq[i].compareTo(pq[j])<0;
    }
    private void resize(int max){
        Key[] temp=(Key[]) new Comparable[max];
        for(int i=1;i<=N;i++){
            temp[i]=pq[i];
        }
        pq=temp;
    }
    public static void main(String[] args) {
        MaxPQ pq=new MaxPQ(4);
        pq.insert("P");
        pq.insert("Q");
        pq.insert("E");
        String s=(String)pq.delMax();
        System.out.println(s);
        pq.insert("X");
        pq.insert("A");
        pq.insert("M");
        System.out.println(pq.delMax());
        pq.insert("P");
        pq.insert("L");
        pq.insert("E");
        System.out.println(pq.delMax());
        System.out.println(pq.max());
    }
}

用于堆排序,主要有两个操作,一个是构建有序堆,一个是堆中最大元素的下沉
构建有序堆比如大根堆,可以从最后一个非叶子节点开始进行构造,将其下沉比较,最终获得一个小型的堆,最后构建整个堆结构。

public class HeapSort {
    public void heapSort(Comparable[] a){
        int index=a.length-1;
        //构建有序堆
        for(int i=(index-1)/2;i>=0;i--){
            sink(a,i,index);
        }
        for(int i=index;i>=0;i--){
            swap(a,0,index--);
            sink(a,0,index);
        }
    }

    //N是最后一个元素的位置
    public void sink(Comparable[] a,int k,int N){
        while(2*k+1<=N){
            int j=2*k+1;
            if(j+1<=N && less(a,j,j+1)){
                j++;
            }
            if(less(a,k,j)){
                swap(a,k,j);
                k=j;
            }else{
                break;
            }

        }
    }

    private boolean less(Comparable[] a,int i,int j){
        return a[i].compareTo(a[j])<0;
    }

    private void swap(Comparable[] a,int i,int j){
        Comparable temp=a[i];
        a[i]=a[j];
        a[j]=temp;
    }

    public static void main(String[] args) {
        Integer[] a=new Integer[]{0,2,1,4,3,7,9,6,5,0};
        HeapSort s=new HeapSort();
        s.heapSort(a);
        for(int i=0;i<a.length;i++){
            System.out.print(a[i]+" ");
        }
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值