ヒープのプロパティ
ヒープは完全にバイナリツリーで、実際には配列を介して実装できます。その最も重要なプロパティの1つは、ノードが子ノードよりも小さい(より大きい)ノードが小さいことです。最小のルートノードを備えたヒープは最小のヒープと呼ばれ、最大のルートノードを持つヒープは最大のヒープと呼ばれます。次の図は、最大のヒープとその配列表現の例を示しています。これは、各ノードが子供よりも大きいことを直感的に見ることができます。
上の図に見られるように、完全にバイナリツリーのノードは、配列Aのインデックスに対応するルートノード番号1から順番に配置できます(ここでのサブスクリプトは1から始まることに注意してください)。ノードIを考えると、左の子供を簡単に手に入れることができます。
ヒープの基本操作
ヒープには2つの基本操作があります(以下の例として最小ヒープを参照):
要素K:k:kを配列の端に直接追加し、ヒープを調整するために泡立てます。バブルアップ操作:親ノードに調整する要素を比較し、親ノードよりも大きい場合は、ヒープのプロパティが復元されるまで交換します。
最も価値を抽出します:最も値がルート要素です。次に、削除し、ルート要素=最後のリーフノード要素とし、ルート要素からバブルダウンしてヒープを調整します。バブルダウン操作:毎回、3つのノードから最小の子ノードを選択して、左右の子供が交換するためのノードを調整する必要があります(最小の場合は、それ自体を交換する必要はありません)。
実際には、n要素を含む順序付けられていないアレイをヒープに組み込む必要があることがよくあります。以下のヒープクラスのコンストラクターは、_bubbledownバブルダウン調整を介してヒープを構築する方法を示します。ヒープは本質的に完全にバイナリツリーであり、ツリーの高さは常にlognlognです。各基本操作の時間のかかる操作は、ヒープの特性を満たすために泡立ち、調整することです。そのため、それらの時間の複雑さはO(nlogn)o(nlogn)です。
Javaの例:
// float public void Swim(int k){while(k/2> = 1 && less(pq [k/2]、pq [k])){exch(pq、k/2、k); k = k/2; }} //シンクプライベートvoid sink(){int k = 1; while(2*k <n){int j = 2*k; if(less(pq [j]、pq [j+1]))j ++; if(less(pq [k]、pq [j]))recks(pq、k、j);それ以外の場合は休憩します。 k = j; }}ヒープソートの実装原則
2つのステップに分かれています。
1.バイナリヒープ順に配列を配置します
2。ルートノードと最後のノードの位置を変更し、ルートノードをシンクします。
成し遂げる:
私のコードは上記のアニメーションとはわずかに異なるかもしれませんが、基本原則は似ています。
Public Class HeapsortはBasesortを拡張します{private int n; @Override public void sort(comparable [] a){n = a.length-1; int k = n/2; while(k> = 1){sink(a、k); k--; } k = 1; while(k <= n){Exch(a、k、n - );シンク(a、k); }}}