优先队列详解,你还不懂优先队列?

          优先队列是一个常见的堆的应用,他是一种维护一组元素构成的集合S的数据结构。优先队列分为最大优先队列最小优先队列,在优先队列中,每一个元素都有一个关键字(key),这个关键字可以用来判别优先队列中元素在所有元素中的优先级。这里我以最大优先队列来举例优先队列里面常见的操作:

1.INSERT(S,x):把元素x插入到集合S里面。
2.MAXIMUM(S):返回S里面关键字key最大的元素
3.EXTRACT-MAX(S):去掉并返回S中的具有最大关键字key的元素
4.INCREASE-KEY(S,x,k):将元素x的关键字值增加到k,这里的k一
	般是大于等于x的原关键字值

最小优先队列相应的操作就是:INSERT,MINIMUM,EXTRACT-MIN,DECREASE-KEY.

一.堆排序

如果你已经学过了堆排序可以直接跳过这一节往下看,如果不熟悉请看下面关于利用大根堆实现排序的算法。

1.堆调整

	    /**
     * 我们这里假设i的左子树与右子树
     * 已经成功构建为大根堆,然后对索引i处的值作调整,n是数组a的大小
     * @param a
     * @param i
     * @param n
     */
    void heapify(int[] a,int i,int n){
        int largest = i;
        if(2*i+1<=n-1&&a[2*i+1]>a[largest]){
            largest = 2*i+1;
        }
        if(2*i+2<=n-1&&a[2*i+2]>a[largest]){
            largest = 2*i+2;
        }
        if(largest!=i){
            swap(a,largest,i);
            heapify(a,largest,n);
        }
    }

在这里插入图片描述
在这里插入图片描述
这个方法最坏时间复杂度是O(h),这里的h是从索引i位置开始到最下面又多高。

2.构建堆

      void buildMaxHeap(int []a){
        int end = (a.length-2)/2;
        for(int i = end;i>=0;i--){
            heapify(a,i,a.length);
        }
    }

这个构建大根堆的过程就是多次调用heapify,下面我们来分析复杂度:
在这里插入图片描述
在这里插入图片描述

3.堆排序算法实现

void heapSort(int []a){
        buildMaxHeap(a);
        for(int i=a.length-1;i>=1;i--){
            swap(a,0,i);
            heapify(a,0,i);
        }
    }

第一步是先构造大根堆,接下来一直做如下操作:
1.把索引0的值与最后一个元素交换,数组长度n减1
2.重新调整堆结构,调用heapify(a,0,n)
上述最后在n==1时结束,代码中i就是变化的n的值

这个算法是时间复杂度为:
O(n)+(n-1)*O(logn)=O(nlogn)

二.实现优先队列

	//复杂度O(1)
    int MAXMUM(int []a){
        return a[0];
    }

    //复杂度O(logn)
    int EXTRACT_MAX(int []a){
        int max  = a[0];
        swap(a,0,length-1);
        heapify(a,0,length-1);
        length--;
        return max;
    }
    
	//复杂度O(logn)
    void INCERASE_KEY(int []a,int i,int key){
        if(i<=length-1&&key>a[i]){
            int current =  i;
            while(a[current]>a[(current-1)/2]){
                swap(a,current,(current-1)/2);
                current = (current-1)/2;
            }
        }
    }

关于INSERT,这里的集合结构不应该是数组,我们采用list,具体的做法便是:

将负无穷放在list最后,最后这个元素索引记为index,然后调用INCERASE_KEY(list,index,key)即可。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值