堆排序的最坏运行时间和最优运行时间

1964年Williams发明的,1992年Sedgewick发表了堆排序性能分析 "The analysis of heapsort"。
所以求堆排序的最优运行时间比较难。

一、最坏运行时间


由于前面已经证明了:在n个元素的堆中,MAX-HEAPIFY的最坏运行时间为 Ω(lgn)。
如果要求堆排序的最坏运行时间,则可以假设每次MAX-HEAPIFY都是最坏运行时间。
堆T为一般堆,即可能是满二叉树,也可能不是满二叉树,如果不是满二叉树,则将最下面一层删除后变成满二叉树,即为T‘。
设F()为最坏运行时间,则F(T)>=F(T').

我们只要求F(T')= Ω (nlgn)即可。


所以得证。

二、最优运行时间



假设要堆排序的堆T不是满二叉树,则我们可以将最下层的叶子节点去除,使其变成满二叉树T‘,我们可以说明对T’堆排序的最优时间一定小于对T堆排序的最优时间,即如果设f()为堆排序的优有时间,则f(T)>f(T')。

因此我们先考虑对满二叉树排序,首先给出几个命题。

命题:假设有k层满二叉树,即高度为k-1,经过2^(k-1)次EXTRACT-MAX即将堆的高度减少一层后,这2^(k-1)个节点中至少还有2^(k-1)/2仍在堆中。

证明:
首先给出两个性质,
(1)如果要删除儿子节点,必须先删除父亲节点,因为EXTRACT-MAX是从大到小的,而父亲节点肯定比儿子节点大,所以父亲肯定比儿子节点要先被EXTRACT。
(2)如果在第k层有m个点要删除,则在第k-1层,至少有ceil(m/2)个点要删除,比如第k层有2个节点要删除,则如果两个节点有共同父亲,则在k-1层中至少删除其父亲,如果两个节点没有共同父亲,则至少要删除它们的父亲后才能够删除它们。

我们如果证明了可以有2^(k-1)/2个节点在堆中,则大于2^(k-1)/2个节点在堆中就不需要证明了。

当有2^(k-1)/2个节点在堆中,则有2^(k-2)个节点不在堆中,在他的上一层至少有ceil(2^(k-1)/4)=2^(k-3)个节点不在堆中,以此类推,在第一层有1个节点不在堆中。
因此这些不在堆中的节点加起来:2^(k-2)+2^(k-3)+....+2^0=2^(k-1)-1,个数小于EXTRACT-MAX的次数,因此可能,因为如果肯定不在堆中的点的个数大于EXTRACT-MAX的次数,则说明不可能。

当有2^(k-1)/2+1 个节点不在堆中,则上一层有2^(k-3)+1个节点不在堆中,类推,则第一层有1个节点不在堆中。
这些点加起来:2^(k-2)+1+....2^0=2^(k-1)-1+k-1=2^(k-1)+k-2,因此当k>2时这个个数就大于EXTRACT-MAX的次数了,所以不成立,因此得证。


因为经过2^(k-1)次EXTRACT-MAX后至少有2^(k-1)/2个节点在堆中,所以至多有2^(k-1)/2个节点不在堆中,因为2^(k-1)次EXTRACT-MAX需要拿走2^(k-1)个节点,因此在1~k-1层中至少有2^(k-2)个节点不在堆中,即会被拿走。

命题:对于一棵k层满二叉树,任意非叶子节点都只能通过swap操作往上走,而不能往下走。

证明:这个很显然。

因为上面的命题,所以对于1~k-1层至少2^(k-2)个非叶子节点,如果要被拿走,只能通过swap操作往上走,因此最好情况分析就是swap操作至少做几次。
假设这些节点全部塞满1~k-2层,一共2^(k-2)-1个,全部都swap到根节点需要:
k=Θ(lgn),所以
2^0 * 0 + 2^1 * 1 + 2^2 * 2 + ..... + 2^(K-3) *(K-3)=Θ(nlgn)

所以k->k-1层需要Θ(nlgn),所以k->k-2层也是,以此类推,所以最优情况复杂度为Θ(nlgn)=Ω(nlgn)

满二叉树考虑好了,假设给定一棵一般树,结点个数为n,则将最下面一层的叶子去除,就变成了一棵满二叉树,而最下面一层最多为n/2,所以m=(n-n/2)=n/2为满二叉树的节点个数,因为满二叉树的复杂度为:Ω(mlgm)=Ω((n/2)lg(n/2))=Ω(nlgn)
所以一般树肯定大于等于Ω(nlgn),所以肯定也是Ω(nlgn)




你可能感兴趣的:(【算法导论】)