heapifyの再帰的バージョンはありません(下記の例を参照)。クイックソートの場合、再帰が小さいパーティションでのみ使用されている場合は、ループして大きなパーティションを2に分割し(2つのパーティションの小さい方のパーティションでも再帰を使用)、最大スタック領域はO(log n))、最悪の時間はまだO(n^2)です。非再帰heapify有する非再帰ヒープソートの
C++例:実装は愚かでない限り
typedef unsigned int uint32_t;
void HeapSort(uint32_t *, size_t);
void Heapify(uint32_t *, size_t);
void SiftDown(uint32_t *, size_t, size_t);
void HeapSort(uint32_t * a, size_t count)
{
size_t end;
Heapify(a, count); // create initial heap
end = count-1;
while(end > 0){
// swap root (largest value) with end
std::swap(a[0], a[end]);
// reduce size of heap and
// increase size of sorted array
end--;
// repair the reduced heap
SiftDown(a, 0, end);
}
}
// create initial heap: for root = (count-2)/2 -> 0
// parent = root, children = root*2+1, root*2+2
// swap so that all a[parent] > a[child]
void Heapify(uint32_t * a, size_t count)
{
size_t root;
if(count < 2)
return;
// create sub-heaps of increasing size,
// with root going from (count-2)/2 to 0
root = (count - 2)/2;
while(1){
SiftDown(a, root, count-1);
if(root == 0)
break;
root--;
}
}
// scan from root to end, swapping as needed to repair or create heap
void SiftDown(uint32_t * a, size_t root, size_t end){
size_t parent;
size_t child;
// while at least two children
for(parent = root; (child = parent * 2 + 2) <= end;){
// choose the larger child
if(a[child-1] > a[child])
child = child-1;
// if child > parent then swap, parent = child
if(a[child] > a[parent]){
std::swap(a[child], a[parent]);
parent = child;
// else done with search for swaps
} else {
break;
}
}
// check for final only child
if((child = parent * 2 + 1) <= end)
if(a[child] > a[parent])
std::swap(a[child], a[parent]);
}
クイックソートはO(ログn)空間を使用します。 – gnasher729
[なぜヒープソートにはO(1)の空間複雑さがありますか?](http://stackoverflow.com/questions/22233532/why-does-heap-sort-have-a-space-complexity-of -o1) –
Wikiは '' 'O(1)' ''を書くのではなく、 '' 'O(1)auxiliary'''を書いています! – sascha