Le concept d'arbre binaire (tas)
Un arbre binaire (tas) est une structure: chaque nœud peut avoir deux nœuds enfants, formant ainsi une structure arborescente inversée, et un tableau peut également être considéré comme un arbre binaire, chaque nœud de l'arbre binaire peut être considéré comme l'un des tableaux Élément.
10
23 25
134 135 9
L'arbre binaire tel qu'illustré correspond au tableau [10,23,25,134,135,9].
Si chaque nœud du tas est plus grand que ses deux nœuds enfants, nous appelons cet arbre binaire le plus grand tas.
Si le sous-arbre d'un nœud i satisfait la propriété de tas maximale, nous pouvons l'échanger avec les deux sous-arbres pour le plus grand tas, et le sous-tas avec i comme nœud deviendra le tas maximum. Voici le code:
/**
* 如果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;
}
Comment dire qu'un tableau ordinaire est généré comme tas maximum?
Le code suivant peut être fait:
/**
* 生成最大堆
*
* @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;
}
Il peut garantir que les nœuds i, i + 1, n, n sont le tas maximum après chaque cycle.
- Il a été clairement établi au début, car ces nœuds étaient initialement des nœuds enfants.
- Après chaque cycle, l'i-node a la propriété de segment de mémoire maximale et la propriété de segment de mémoire maximale du nœud après la modification n'est pas modifiée.
- Lorsque la boucle se termine, le tableau entier devient le plus grand tas.
L'algorithme ci-dessus peut être complété en temps linéaire.
Tri par tas
Nous avons pu convertir le tableau en tas maximum en temps O (n), et nous voulons le trier.
La première étape: déplacez la valeur maximale, c'est-à-dire le nœud racine, hors du tas maximal et échangez-la avec le dernier élément du tableau. À ce stade, la n-ième ligne est la valeur maximale du tableau et les n-1 premiers nombres ne sont pas le segment maximal, car le nœud racine peut ne pas respecter la nature de segment maximale.
Deuxième étape: conserver le nombre n-1 précédent comme tas maximum. Puisqu'un nœud n'est pas satisfait, toute cette opération peut être effectuée en temps linéaire.
Dans la troisième partie, la valeur maximale du plus grand tas composé des n-1 précédents est échangée avec le numéro le plus élevé suivant du tableau.
Répétez les étapes ci-dessus pour trier le tableau.
Voici le code complet:
/**
* @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;
}
}