我试图了解不同数据结构的时间复杂性,并从堆排序开始。根据我的阅读,我认为人们普遍认为堆排序的时间复杂度为O(nlogn);但是,我很难理解它是如何发生的。
大多数人似乎都同意heapify方法采用O(logn),buildmaxheap方法采用O(n)从而采用O(nlogn),但是为什么heapify采用O(logn)?
在我看来,heapify似乎只是一种比较节点左右节点并根据其是最小堆还是最大堆正确交换它们的方法。为什么要用O(logn)?
我想我在这里错过了一些东西,如果有人可以向我更好地解释这一点,我将不胜感激。
谢谢。
答案 0 :(得分:0)
您在heapify方法末尾缺少递归调用。
Heapify(A, i) {
le <- left(i)
ri <- right(i)
if (le<=heapsize) and (A[le]>A[i])
largest <- le
else
largest <- i
if (ri<=heapsize) and (A[ri]>A[largest])
largest <- ri
if (largest != i) {
exchange A[i] <-> A[largest]
Heapify(A, largest)
}
}
在最坏的情况下,每一步之后,largest
大约是i
的两倍。为了使i到达堆的末尾,需要执行O(logn)
个步骤。
答案 1 :(得分:0)
似乎您对堆排序的时间复杂性感到困惑。的确,从未排序的数组构建maxheap会花费O(n)时间和O(1)来弹出一个元素。但是,从堆中弹出顶部元素后,需要将堆中的最后一个元素(A)移到顶部,并且要保持堆的性质,以保持堆属性。对于元素A,最多最多弹出log(n)次,这是堆的高度。因此,在弹出最大值之后,您最多需要log(n)时间才能获得下一个最大值。这是堆排序过程的示例。
18
15 8
7 11 1 2
3 6 4 9
弹出数字18后,需要将数字9放在顶部并堆9。
9
15 8
7 11 1 2
3 6 4
由于9 <15
,我们需要将9弹出 15
9 8
7 11 1 2
3 6 4
由于9 <11
,我们需要将9弹出 15
11 8
7 9 1 2
3 6 4
9> 4表示堆化过程已完成。现在,您可以安全地获得下一个最大值15,而无需断开堆属性。
您执行堆化过程所需的每个数字都有n个数字。所以堆排序的时间复杂度是O(nlogn)