为什么堆排序的空间复杂度为O(1)?

我知道快速排序和合并排序需要O(n)辅助空间用于构建的临时子数组,并且就地快速排序需要O(log n)递归堆栈帧的辅助空间。 但是对于堆排序来说,它似乎也有一个最坏情况的O(n)辅助空间来构建临时堆,即使节点只是指向实际元素的指针。

我遇到了这样的解释:

只需要O(1)个额外的空间,因为堆是在数组内部进行排序的。

但我认为这意味着原始数组必须已经被实现为某种树? 如果原始数组只是一个向量,看起来堆内存仍然需要分配。


数组中的数据可以重新排列成堆。 这个算法实际上非常简单,但我不会在这里讨论它。

对于堆排序,您可以排列数据,以便它形成一个堆,最后一个元素位于后面( std::make_heap )。 然后,将数组中的最后一项(堆中的最小项)与数组中的第一项(较大数字)进行交换,然后将堆中的那个大元素转换到堆中,直到它处于新的适当位置,堆再次创建一个新的分钟堆,并在数组的最后一个元素中留下最小的剩余元素。 ( std::pop_heap

data:         1 4 7 2 5 8 9 3 6 0

make_heap:   [8 7 9 3 4 5 6 2 1 0] <- this is a min-heap, smallest on right

pop_heap(1): [0 7 9 3 4 5 6 2 1 8] <- swap first and last elements
pop_heap(2): 0 [7 9 3 4 8 6 2 5 1] <- shuffle the 8 down the heap

pop_heap(1): 0 1 [9 3 4 8 6 2 5 7] <- swap first and last elements
pop_heap(2): 0 1 [9 7 4 8 6 3 5 2] <- shuffle the 7 down the heap

etc

所以没有数据实际上需要存储在其他地方,除了在交换步骤期间。

为了可视化,这是以标准形式显示的原始堆

make_heap 
           0
     2           1
  3     4     5     6
               8   7 9
pop_heap
           8                           1                           1
     2           1               2           8               2           5 
  3     4     5     6    ->   3     4     5     6    ->   3     4     8     6 
                   7 9                         7 9                         7 9

这里很酷的技巧是因为堆是一个完整的二叉树,你可以使用一个普通的数组,而对于第i个项,它的父项就是项目i/2

链接地址: http://www.djcxy.com/p/40049.html

上一篇: Why does heap sort have a space complexity of O(1)?

下一篇: How to calculate growth rate using Big O?