算法 第二章--优先队列

2.4优先队列

先介绍两个动作方法。1.下沉 2.上浮


 1. 下沉 

//下沉  k指的是父节点
    private void sink(int k){
        //子节点为 2*k,只要子节点 不大于N,即还没有下沉完
        while(2*k <= N){
            int j = 2*k;
            //先比较该元素的两个子节点,如果左节点  小于  右节点,则进行交换,选一个较大的子节点与父节点进行比较
            if(j < N && less(j,j+1) ) j++;
            //如果 较大的子节点 都小于父节点,就结束 下沉;否则交换。
            if(!less(k,j))break;

            exch(k,j);
            //把刚交换的子节点  换给k,进入下一次的比较
            k=j;
        }
    }

2.上浮

//上浮
    private void swim(int k){
        //只要k>1,且k/2 为它的父节点,小于它,即:进行交换
        while(k>1 &&less(k/2,k)){
            exch(k/2,k);
            k = k/2;
        }
    }

优先队列:是一种抽象数据类型。API 见p195, 最重要的操作就是 :
1. 删除最大元素。
2. 插入元素。
具体实现如下:

//仅仅实现了  删除最大的元素(返回最大元素),和使堆有序化
public class MaxPQ<Key extends Comparable<Key>> {
    private Key[] pq;//基于堆的完全按二叉树,存储于qp[1...N],qp[0]没有使用
    private int N = 0;//计数

    //创建数组
    public MaxPQ(int maxN){ 
        pq = (Key[])new Comparable[maxN+1];
    }

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

    public int size(){
        return N;
    }

    public void insert(Key v){
        pq[++N] =v; 
    }
    /*
     * 删除元素
     * 
     */
    public Key delMax(){
        //把根节点 赋给 max,因为它是最大的
        Key max = pq[1];
        //让最后一个元素 顶替 根元素
        exch(1,N--);
        pq[N+1] = null;
        //下沉它
        sink(1);
        return max;
    }
    //下沉  k指的是父节点
    private void sink(int k){
        //子节点为 2*k,只要子节点 不大于N,即还没有下沉完
        while(2*k <= N){
            int j = 2*k;
            //先比较该元素的两个子节点,如果左节点  小于  右节点,则进行交换,选一个较大的子节点与父节点进行比较
            if(j < N && less(j,j+1) ) j++;
            //如果 较大的子节点 都小于父节点,就结束 下沉;否则交换。
            if(!less(k,j))break;

            exch(k,j);
            //把刚交换的子节点  换给k,进入下一次的比较
            k=j;
        }
    }

    //pq[v]小,pq[m]大  
    public boolean less(int v, int m ){
        return pq[v].compareTo(pq[m])<0;
    }


}
    //交换
    public void exch(int i, int j){
        Key t = pq[i]; 
        pq[i]= pq[j];
        pq[j]= pq[i]; 
    }

最后:讲一下堆排序;

    public static void sort(Comparable[] a){
        int N = a.length;
        //数组a,使它符合 有序堆----构造有序堆
        //k = N/2 为最后的一个父节点,因为N为最后的叶子节点。一次遍历父节点,则是它下沉,使之成为有序堆
        for(int k = N/2; k>=1; k--){
            sink(a,k,N);
        }
        //因为1为堆的根节点,为最大。所以先把它(最大的元素)放在最后。sink()再使之成为有序堆。反复直到为空。
        while(N>1){
            exch(a,1,N--);
            sink(a,1,N);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值