目次
src/runoob/heap/HeapShiftDown.java ファイルコード:
スタックシフトダウン
ここではシフトダウンと呼ばれる最大ヒープから要素を取り出す方法を紹介します 最も優先度の高い要素、つまりルートノードのみを取り出すことができます 元の62を取り出した後、以下のように記述します最大ヒープを埋める方法。
最初のステップでは、配列の最後の桁をルート ノードに置きますが、現時点では最大ヒープの定義を満たしていません。
調整方法は、子ノードよりも小さいルートノード16を段階的に下に移動し、まず子ノード52と子ノード30の大きい方を比較し、大きい方と位置を入れ替えます。
引き続き 16 の子ノード 28 と 41 を比較します。41 の方が大きいため、16 と 41 の位置が交換されます。
16 と子ノード 15 の比較を続けます。16 の方が大きいため、今すぐ交換する必要はありません。最終的に、最大ヒープの性質を維持してシフトダウン操作が完了します。
4. Java サンプルコード
ソース パッケージのダウンロード: https://www.runoob.com/wp-content/uploads/2020/09/runoob-algorithm-HeapShiftDown.zipをダウンロードします。
src/runoob/heap/HeapShiftDown.java ファイルコード:
package runoob.heap;
/**
* 最大のヒープから要素を取り出す
*/
public class HeapShiftDown<T extends Comparable> { protected T[] data; protected int count; protected int Capacity; // コンストラクター、空のヒープを構築する、容量要素を保持できます public HeapShiftDown(int Capacity){ //ここで 1 を追加すると、元々ロードできる要素の数を指します。その後 0 を削除すると、容量要素のみをロードできます。 data = (T[])new Comparable[ Capacity +1]; count = 0; this.capacity = Capacity; } // ヒープ内の要素の数を返します public int size(){ return count; } // ヒープが空かどうかを示すブール値を返します public boolean isEmpty (){ 戻り値 == 0;
}
// 新しい要素を最大ヒープに挿入します item
public void insert(T item){ assert count + 1 <= Capacity; data[count+1] = item; count ++; shftUp(count); } // Take最大ヒープから最上位の要素、つまりヒープに格納されている最大データを取り出します public T extractMax(){ assert count > 0; T ret = data[1]; swap( 1 , count ); count --; ShiftDown (1 ); return ret; } // 最大ヒープの最上位要素を取得します public T getMax(){ assert( count > 0 ); return data[1]; } // 2 つの要素をインデックス i と j で交換しますヒープ
private void swap(int i, int j){ T t = data[i]; data[i] = data[j]; data[j] = t; } //********** * ******** //* 最大ヒープコアヘルパー関数 //********************* private void shftUp(int k){ while( k > 1 && data[k/2].compareTo(data[k]) < 0 ){ swap(k, k/2); k /= 2; } } //shiftDown 操作 private void shftDown(int k){ while ( 2*k <= count ){ int j = 2*k; // このサイクルでは、data[k] と data[j] の位置が交換されます if( j+1 <= count && data[j+1] .compareTo(データ[j]) > 0 ) j ++;
// data[j] は data[2*k] と data[2*k+1] の最大値
if( data[k].compareTo(data[j]) >= 0 ) Break;
swap(k, j);
k = j;
}
System.out.println("end of shftDown");
}
// HeapShiftDown をテスト
public static void main(String[] args) { HeapShiftDown<Integer> heapShiftDown = new HeapShiftDown<Integer>(100 ) ; // ヒープ内の要素の数 int N = 100; // ヒープ内の要素の値の範囲 [0, M) int M = 100; for( int i = 0 ; i < N ; i ++ ) heapShiftDown .insert( new Integer((int)(Math.random() * M)) ); Integer[] arr = new Integer[N];
// extractMax を使用して最大ヒープ内のデータを徐々に抽出します
// 抽出の順序は大きいものから小さいものにする必要があります
for( int i = 0 ; i < N ; i ++ ){ arr[i ] = heapShiftDown.extractMax() ; System.out.print(arr[i] + " "); } // arr 配列が最大から最小の順に配置されていることを確認します for( int i = 1 ; i < N ; i ++ ) assert arr[i- 1] >= arr[i]; } }