Answers:
我的意思是用要排序的数组元素(即堆)填充的额外数据结构用于协助最小值的提取和排序过程。
不。将数组转换为符合堆约束,而无需使用超过O(1)的额外内存。(实际上,您需要的额外内存足以容纳数组的一个元素(用于交换),再加上一个或两个布尔值以及一个或两个循环变量)。
好的,从技术上讲,通常可以将堆排序解释为使用单独的堆,但是完全可以就地实现它。
您可能缺少基本的理解,即可以使用数组来指定树的布局。
假设您有一棵二叉树,并且内部节点位于数组的索引i处。然后可以通过以下方式找到该节点的父级和子级的数组索引:
Parent(i) = floor(i/2)
Left child(i) = 2i
Right child(i) = 2i + 1
看到:
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/Sorting/heapSort.htm
由于可以将堆完全保留和组织在一个数组中,因此可以通过在输入数组内部移动元素来使heapsort在原地运行。实际上,堆是使用原始输入数组构建和操纵的。
如您所说,如果确实需要一个额外的结构来构建堆,那么heapsort确实不是就地排序算法。
然而,这种情况并非如此。您可以在要排序的同一数组上构建堆,然后应用heapsort算法,以便就地排序。
在计算机科学中,就地算法(或就地拉丁语而言)是一种使用数据结构转换输入的算法,该数据结构具有少量恒定的额外存储空间。算法执行时,输入通常会被输出覆盖。非原位算法有时称为非原位或非原位。
之所以认为它是适当的,是因为它的空间要求可以忽略不计(如果您使用按位运算来交换项目,则它的常数是恒定的,或者根本不存在)。例如,没有MergeSort,因为在搜索示例的每次迭代中都没有修改输入集。
说明就地算法与就地算法之间差异的最好方法可能是看一下下面的C / C ++字符串反转代码(从K&R开始):
void reverse(char s[])
{
int c, i, j;
for (i = 0, j = strlen(s)-1; i < j; i++, j--) {
c = s[i];
s[i] = s[j];
s[j] = c;
}
}
例如,如果您从末尾读取输入字符串并将字符放置在另一个缓冲区中,那将是一种异位字符串反转算法。