任意の配列をヒープに変換し (これを「ヒープ ビルド」と呼びます)、それをヒープソートで並べ替える複雑さを計算する方法を「数学的に」示しましょう。
ヒープ構築時間分析
配列をヒープに変換するには、子を持つ各ノードを見て、そのノードを「ヒープ化」(シンク) する必要があります。実行する比較の数を自問する必要があります。考えてみると、次のことがわかります (h = 木の高さ):
- レベル i の各ノードに対して、hi 比較を行います: #comparesOneNode(i) = hi
- レベル i には、2^i ノードがあります: #nodes(i) = 2^i
- したがって、一般に T(n,i) = #nodes(i) * #comparesOneNode(i) = 2^i *(hi) は、レベル「i」での「比較」に費やされた時間です。
例を挙げましょう。15 要素の配列があるとします。つまり、ツリーの高さは h = log2(15) = 3 になります。
- レベル i=3 では、2^3=8 個のノードがあり、ノードごとに 3 ~ 3 回の比較を行います。レベル 3 では、子を持たないノード、つまり葉しかないため、正解です。T(n, 3) = 2^3*(3-3) = 0
- レベル i=2 では、2^2=4 個のノードがあり、ノードごとに 3-2 回の比較を行います。レベル 2 では比較できるレベル 3 しかないため、正解です。T(n, 2) = 2^2*(3-2) = 4 * 1
- レベル i=1 では、2^1=2 個のノードがあり、各ノードに対して 3-1 回の比較を行います: T(n, 1) = 2^1*(3-1) = 2 * 2
- レベル i=0 では、ルートである 2^0=1 ノードがあり、3-0 比較を行います: T(n, 0) = 2^0*(3-0) = 1 * 3
わかりました、一般的に:
T(n) = sum(i=0 ~ h) 2^i * (hi)
しかし、h = log2(n) を覚えていれば、
T(n) = sum(i=0 から log2(n)) 2^i * (log2(n) - i) =~ 2n
ヒープソート時間分析
さて、ここでの分析は非常に似ています。最大要素 (ルート) を「削除」するたびに、ツリーの最後のリーフをルートに移動し、それをヒープ化し、最後まで繰り返します。では、ここで実行する比較の数は?
- レベル i には、2^i ノードがあります: #nodes(i) = 2^i
- レベル「i」の各ノードに対して、最悪の場合、heapify は常にレベル「i」とまったく同じ数の比較を行います (レベル i から 1 つのノードを取得し、それをルートに移動し、heapify を呼び出します)。 、最悪の場合、heapify はノードをレベル i に戻し、"i" 比較を実行します): #comparesOneNode(i) = i
- したがって、一般に T(n,i) = #nodes(i) * #comparesOneNode(i) = 2^i*i は、最初の 2^i のルートを削除し、一時的なルートを正しい位置に戻すために費やされた時間です。 .
例を挙げましょう。15 要素の配列があるとします。つまり、ツリーの高さは h = log2(15) = 3 になります。
- レベル i=3 では、2^3=8 個のノードがあり、それぞれをルートの場所に移動してから、それぞれをヒープ化する必要があります。ルートがまだ存在するレベル "i" に沈む可能性があるため、各 heapify は最悪の場合の "i" 比較で実行されます。T(n, 3) = 2^3 * 3 = 8*3
- レベル i=2 では、2^2=4 ノードがあり、ノードごとに 2 つの比較を行います: T(n, 2) = 2^2*2 = 4 * 2
- レベル i=1 では、2^1=2 ノードがあり、ノードごとに 1 つの比較を行います: T(n, 1) = 2^1*1 = 2 * 1
- レベル i=0 では、ルートである 2^0=1 ノードがあり、0 の比較を行います: T(n, 0) = 0
わかりました、一般的に:
T(n) = sum(i=0~h) 2^i * i
しかし、h = log2(n) を覚えていれば、
T(n) = sum(i=0 から log2(n)) 2^i * i =~ 2nlogn
ヒープビルド VS ヒープソート
直観的に、ヒープ ソートはコストを「償却」できないことがわかります。これは、ノード数を増やすたびに比較を行う必要があるためです。ヒープ ビルド機能は正反対です。ここで見ることができます:
- ヒープ構築: T(n, i) ~ 2^i * (hi)、i が増加すると、#nodes は増加しますが、#compares は減少します
- ヒープソート: T(n, i) ~ 2^i * i、i が増加すると、#nodes が増加し、#compares が増加します
そう:
- レベル i=3、#nodes(3)=8、ヒープ ビルドは 0 回の比較を行い、ヒープソートは 8*3 = 24 回の比較を行います
- レベル i=2、#nodes(2)=4、ヒープ ビルドは 4 回の比較を行い、ヒープソートは 4*2 = 8 回の比較を行います
- レベル i=1、#nodes(1)=2、ヒープ ビルドは 4 回の比較を行い、ヒープソートは 2*1 = 2 回の比較を行います
- レベル i=0、#nodes(0)=1、ヒープ ビルドは 3 回の比較を行い、ヒープソートは 1*0 = 1 回の比較を行います