堆排序的最坏运行时间和最优运行时间
2012-11-17 13:23
204 查看
1964年Williams发明的,1992年Sedgewick发表了堆排序性能分析 "The analysis of heapsort"。
所以求堆排序的最优运行时间比较难。
如果要求堆排序的最坏运行时间,则可以假设每次MAX-HEAPIFY都是最坏运行时间。
堆T为一般堆,即可能是满二叉树,也可能不是满二叉树,如果不是满二叉树,则将最下面一层删除后变成满二叉树,即为T‘。
设F()为最坏运行时间,则F(T)>=F(T').
我们只要求F(T')=Ω(nlgn)即可。
所以得证。
因此我们先考虑对满二叉树排序,首先给出几个命题。
命题:假设有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)
所以求堆排序的最优运行时间比较难。
一、最坏运行时间
由于前面已经证明了:在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)
相关文章推荐
- 题目2.给出一个算法,它能用O(nlgn)的最坏情况运行时间,确定n个元素的任何排列中逆序对的数目
- 第九章中位数和顺序统计学 之 “寻找第i小元素之最坏情况线性时间的选择 最坏运行时间就为O(n)算法”
- 改进合并排序法以查找元素序列中的逆序对数量,最坏运行时间O( nlog2(n) )
- 一种最坏情况线性运行时间的选择算法 - The missing worst-case linear-time Select algorithm in CLRS.
- 最优装载 时间限制(普通/Java):3000MS/10000MS 运行内存限制:65536KByte
- 提出一种数据结构支持push和pop操作以及第三种操作findMin,返回最小值,所有操作均以O(1)最坏时间运行
- 提出支持栈的Push和Pop操作以及第三种操作FindMin的数据结构,其中FindMin返回该数据结构的最小元素 所有操作在最坏的情况下的运行时间都是O(1)
- 一种最坏情况线性运行时间的选择算法 - The missing worst-case linear-time Select algorithm in CLRS.
- 最坏情况快速排序的运行时间为Ο(nlgn)的算法
- 提出一种数据结构支持pop push 和findMin,并且每种操作的运行时间最坏为O(1)
- c#计算程序的运行时间
- 【c++】检测一个函数运行的时间
- 算法学习—算法运行时间、logN、NlogN
- 掌握程序的实际运行时间
- 利用boost计算运行时间间隔及获取系统时间并格式化
- 1026. 程序运行时间(15)
- 关于计算Java程序运行时间
- linux查看进程启动时间、运行多长时间等指定信息
- PAT 乙级 1026. 程序运行时间(15) Java版
- C#中提供的精准测试程序运行时间的类Stopwatch