码迷,mamicode.com
首页 > 编程语言 > 详细

算法2.4——优先队列与堆排序

时间:2015-01-26 19:00:22      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

  优先队列(Priority Queues)的使用和队列(删除最老的元素)以及栈(删除最新的元素)类似。举个实用例子:也就是从10亿个元素中选出最大的10个,有了优先队列,就只需要用一个能存储10个元素的队列即可。

  而二叉堆很好实现优先队列的基本操作。其中二叉堆是一组能够用队友徐的完全二叉树排序的元素。其中关于堆的算法,有上浮swim和下沉sink,另外一般来说A[0]不使用,直接使用A[1]。

  堆排序的实现

  实现堆排序需要解决两个问题:

    1.如何由一个无序序列建成一个堆?

    2.如何在输出堆顶元素之后,调整剩余元素成为一个新的堆? 

    第二个问题,一般在输出堆顶元素之后,视为将这个元素排除,然后用表中最后一个元素填补它的位置,自上向下进行调整:首先将堆顶元素和它的左右子树的根结点进行比较,把最小的元素交换到堆顶;然后顺着被破坏的路径一路调整下去,直至叶子结点,就得到新的堆。

  我们称这个自堆顶至叶子的调整过程为“筛选”。

  从无序序列建立堆的过程就是一个反复“筛选”的过程。

 

实例过程:

建立初始的堆结构如图:技术分享

然后,交换堆顶的元素和最后一个元素,此时最后一个位置作为有序区(有序区显示为黄色),然后进行其他无序区的堆调整,重新得到大顶堆后,交换堆顶和倒数第二个元素的位置:技术分享

重复上述步骤:技术分享

 

代码实现(java):


public class Heap {


private Heap() { }

public static void sort(Comparable[] pq) {
int N = pq.length;
for (int k = N/2; k >= 1; k--) //构造堆
sink(pq, k, N);
while (N > 1) { //交换修复堆
exch(pq, 1, N--);
sink(pq, 1, N);
}
}


private static void sink(Comparable[] pq, int k, int N) {
while (2*k <= N) {
int j = 2*k;
if (j < N && less(pq, j, j+1)) j++;
if (!less(pq, k, j)) break;
exch(pq, k, j);
k = j;
}
}


private static void exch(Object[] pq, int i, int j) {
Object swap = pq[i-1];
pq[i-1] = pq[j-1];
pq[j-1] = swap;
}

HeapSort算法分析:
  堆排序方法对记录数较少的文件并不值得提倡,但对n较大的文件还是很有效的。因为其运行时间主要耗费在建初始堆和调整建新堆时进行的反复“筛选”上。

  堆排序在最坏的情况下,其时间复杂度也为O(nlogn)。相对于快速排序来说,这是堆排序的最大优点。此外,堆排序仅需一个记录大小的供交换用的辅助存储空间。

 

算法2.4——优先队列与堆排序

标签:

原文地址:http://www.cnblogs.com/ykong/p/4250972.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!