バイナリツリー(ヒープ)の概念
バイナリツリー(ヒープ)は構造です。各ノードは2つの子ノードを持つことができるため、逆ツリー構造を形成し、配列もバイナリツリーと見なすことができ、バイナリツリーの各ノードは配列の1つと見なすことができます。要素。
10
23 25
134 135 9
示されているバイナリツリーは、配列[10,23,25,134,135,9]に対応しています。
ヒープの各ノードが2つの子ノードより大きい場合、このバイナリツリーを最大ヒープと呼びます。
ノードiのサブツリーがすべて最大ヒーププロパティを満たす場合、2つのサブツリーをそれより大きなサブツリーに交換し、ノードが最大ヒープになるときにサブヒープをiと交換できます。コードは次のとおりです。
/**
* 如果i节点下是最大堆,将包括i的子树构建成最大堆
*
* @param array
* @param i
* @param heapSize 二叉树的有效长度
* @return
*/
public static int[] maxHeapify(int[] array, int i, int heapSize) {
int l = left(i);
int r = right(i);
int large;
if (l < heapSize && array[l] > array[i]) {
large = l;
} else {
large = i;
}
if (r < heapSize && array[r] > array[large]) {
large = r;
}
if (large != i) {
int a = array[i];
array[i] = array[large];
array[large] = a;
return maxHeapify(array, large, heapSize);
}
return array;
}
通常の配列が最大ヒープとして生成されると言うにはどうすればよいですか?
次のコードを実行できます。
/**
* 生成最大堆
*
* @param array
* @return
*/
public static int[] buildMaxHerp(int[] array) {
for (int i = array.length / 2 - 1; i >= 0; i--) {
maxHeapify(array, i, array.length);
}
return array;
}
ノードi、i + 1、n、nが各サイクル後の最大ヒープであることを保証できます。
- これらのノードは最初は子ノードだったため、最初に明確に確立されました。
- 各サイクルの後、iノードには最大ヒーププロパティがあり、変更後のノードの最大ヒーププロパティは変更されません。
- ループが終了すると、配列全体が最大のヒープになります。
上記のアルゴリズムは線形時間で完了することができます。
ヒープソート
配列をO(n)時間で最大ヒープに変換できたので、それをソートしたいと思います。
最初のステップ:最大値、つまりルートノードを最大ヒープから移動し、配列の最後の要素と入れ替えます。このとき、n番目の行は配列の最大値であり、最初のn-1の数値は最大ヒープではありません。ルートノードが最大ヒープの性質を満たさない可能性があるためです。
2番目のステップ:以前のn-1の数値を最大ヒープとして維持します。1つのノードが満たされていないため、この操作はすべて線形時間で完了できます。
3番目の部分では、前のn-1の数値で構成される最大のヒープの最大値が、次に大きい配列の数値と交換されます。
上記の手順を繰り返して、配列を並べ替えます。
完全なコードは次のとおりです。
/**
* @author xuyu 二叉树排序
*/
public class BinaryTree {
public static void main(String[] args) {
// ArrayUtil.printArray(buildMaxHerp(new int[] { 16, 4, 10, 14, 7, 9, 3, 2, 8, 1 }));
int[] array = { 13, 3112, 1, 12, 3123, 35, 32, 89, 435, 7987, 2364176, 342, 4584, 234 };
ArrayUtil.printArray(heapSort(array));
}
/**
* 堆排序
*
* @return
*/
public static int[] heapSort(int[] array) {
buildMaxHerp(array);
for (int i = array.length - 1; i >= 1; i--) {
int a = array[i];
array[i] = array[0];
array[0] = a;
maxHeapify(array, 0, i);
}
return array;
}
/**
* 生成最大堆
*
* @param array
* @return
*/
public static int[] buildMaxHerp(int[] array) {
for (int i = array.length / 2 - 1; i >= 0; i--) {
maxHeapify(array, i, array.length);
}
return array;
}
/**
* 如果i节点下是最大堆,将包括i的子树构建成最大堆
*
* @param array
* @param i
* @param heapSize 二叉树的有效长度
* @return
*/
public static int[] maxHeapify(int[] array, int i, int heapSize) {
int l = left(i);
int r = right(i);
int large;
if (l < heapSize && array[l] > array[i]) {
large = l;
} else {
large = i;
}
if (r < heapSize && array[r] > array[large]) {
large = r;
}
if (large != i) {
int a = array[i];
array[i] = array[large];
array[large] = a;
return maxHeapify(array, large, heapSize);
}
return array;
}
/**
* 左孩子的下标
*
* @param i
* @return
*/
public static int left(int i) {
return 2 * i + 1;
}
/**
* 右孩子的下标
*
* @param i
* @return
*/
public static int right(int i) {
return 2 * i + 2;
}
}