web-dev-qa-db-ja.com

ヒープソートのスペースの複雑さがO(1)であるのはなぜですか?

クイックソートとマージソートの両方で、構築される一時サブ配列にO(n)補助スペースが必要であり、インプレースクイックソートには再帰スタックフレームにO(log n)補助スペースが必要であることを理解しています。しかし、ヒープソートの場合、ノードが実際の要素への単なるポインタであっても、一時ヒープを構築するためのO(n)補助スペースの最悪のケースもあるようです。

私はこれに出くわしました 説明

ソートする配列内にヒープが構築されるため、O(1)追加スペースのみが必要です。

しかし、これは、元の配列が必ずしも何らかのツリーとして実装されている必要があることを意味すると思いますか?元の配列が単なるベクトルだった場合、ヒープ用のメモリを割り当てる必要があるようです。

32
Herman Tran

配列内のデータは、適切な場所にヒープに再配置できます。このアルゴリズムは実際には驚くほど簡単ですが、ここでは説明しません。

ヒープの並べ替えの場合は、データを配置してヒープを形成し、最小の要素を後ろに配置します(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
31
Mooing Duck

ここでのクールなトリックは、ヒープが完全なバイナリツリーであるため、単純な配列を使用でき、アイテムiの場合、その親はアイテムi/2になります。

2
zw324

ヒープソートはインプレースアルゴリズムです。追加のスペースは必要ありません。要素は、同じ配列内でのみ再帰的に再配置されます。

バイナリヒープまたはツリーが形成されているように見えますが、実際のシナリオでは、ツリーまたはヒープは形成されていません。

0
Parveen Kumar
HEAP-SORT(A)
{
BUILD-MAX-HEAP(A)
if(i= A.length down to 2)
    exchange A[i] with A[1]
    A.heapSize = A.heapSize-1
    MAX-HEAPIFY(A,1)

}

i/pは、ヒープソートアルゴリズムHEAP-SORT(A)に渡される配列に格納されます。配列Aはツリーとして解釈され、その中からBUILD-MAX-HEAPが出て、最後の要素をルートと交換し、そのたびにヒープサイズを1つ減らしてから、MAX-HEAPIFY(A、1)を呼び出します。

これは、配列(A)内でのみ実行するすべての操作です。これは、アルゴリズムにi/pとして指定されます。この操作の実行中に余分なスペースを使用することはありません。つまり、スペースの複雑さ-O(1)です。

0
Rudra