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来自于每次下沉操作最大可能需要的比较).

  • 相关阅读:
    有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。
    C编程实现2的1000次方(使程序中的n=1000即可)
    有n个整数,使其前面各数顺序向后移m个位置,最后m个数变成最前面m个数。
    有一个字符串,内有若干字符,输入一个字符,要求程序将字符串中该字符删去。
    使用静态变量的方法求n!
    数组排序:冒泡法和选择法
    使用函数的递归调用来解决Hanoi(汉诺)塔问题。
    VC5509的通用GEL代码
    字、字节和位的关系
    安装JDK后环境变量的配置
  • 原文地址:https://www.cnblogs.com/hlhdidi/p/5645927.html
Copyright © 2011-2022 走看看