zoukankan      html  css  js  c++  java
  • 算法_优先队列

      优先队列是一种数据结构,它支持删除最大元素和插入元素.可以利用优先队列实现对于数组的高效排序.

      数据结构二叉堆能够很好的实现优先队列的操作,在二叉堆的数组中,每个节点都大于等于它的子节点,这种情况被称为堆有序.而根节点将是堆有序的二叉树中的最大结点.在一个二叉堆中,位置k的节点的父节点的位置为[k/2],而它的两个子节点的位置则分别为2k,2K+1.这样在不使用指针的情况下,我们可以通过计算树的索引实现在树中的上下移动,a[k]向上一层就是a[k/2],向下一层就是令k等于2k或是2k+1.

      下面是基于堆的优先队列的基本实现:

    public class MaxPQ<Key extends Comparable<Key>> {
        private Key[] pq;
        private int N;
        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;
            swim(N);
        }
        private void swim(int k )/*在堆底插入元素的时候,所对应的上浮操作.*/ {
            while(k>1&&less(k/2,k)) {
                exch(k/2,k);
                k=k/2;
            }
        }
        public Key delMax() {
            Key max=pq[1];
            exch(1,N--);    //将其和最后一个结点交换
            pq[N+1]=null;    //防止对象游离
            sink(1);        //回复堆的有序性
            return max;  
        }
        private void sink(int i) {
            while(2*i<=N) {
                int j=2*i;
                if(j<N&&less(j,j+1)) j++;
                if(!less(i,j)) break;
                exch(i,j);
                i=j;
            }
        }
        public void exch(int i, int k) {
            Key t=pq[i];
            pq[i]=pq[k];
            pq[k]=t;
        }
        private boolean less(int i, int k) {
            return pq[i].compareTo(pq[k])<0;
        }
    }

      对于一个N个元素的基于堆的优先级队列,插入元素操作只需不超过lgN+1次比较,删除最大元素的操作只需不超过2lgN次比较.

      通过基于二叉堆的优先队列,可以实现对于数组的排序,开始的时候我们只需要扫描数组中的一半的元素,因此我们可以跳过大小为1的子堆,最后我们在位置1上调用sink方法,扫描结束.堆排序的实现算法如下:

    public static void sort(Comparable[] a) {
            int N=a.length;
            for(int k=N/2;k>=1;k--) {
                sink(a,k,N);
            }
            while(N>1) {
                exch(a,1,N--);
                sink(a,1,N);
            }
        }

      这段代码中,for循环构造了堆,然后while循环将最大的元素a[1]和a[N]交换,然后如此重复直到堆变空,第二阶段将堆中的最大元素删除,然后放入堆缩小后数组空出来的位置.这种算法被称为堆排序算法.将N个元素排序堆排序只需少于2NlgN+2N次比较.(2N来自于堆构造,2NlgN来自于每次下沉操作最大可能需要的比较).

  • 相关阅读:
    分布式系列
    mybatis-generator自动生成代码工具
    mybatis的jdbcType和javaType、oracle,MySQL的对应类型
    spring的@Transactional注解详细用法
    Unity火爆插件Behavior Designer行为树插件学习
    Unity内存优化之视频讲解
    Unity 2018 Game Development in 24 Hours Sams Teach Yourself 3rd Edition
    8 Ball Pool
    Unity设计模式+Java设计模式,讲解+案例+PPT,一次性学会设计模式,拥抱高薪!
    Unity接入微信登录 微信分享 微信支付 支付宝SDK
  • 原文地址:https://www.cnblogs.com/hlhdidi/p/5645927.html
Copyright © 2011-2022 走看看