Tipo de pila
Introducción
La ordenación de pila también es una especie de selección , la peor y mejor complejidad de tiempo promedio es O (nlogn), que es una ordenación inestable
Es un árbol binario completo, el valor de cada nodo es mayor o igual que el valor de sus nodos secundarios izquierdo y derecho ===> empuje grande, tenga en cuenta que no requiere la relación de tamaño entre los nodos secundarios izquierdo y derecho , de lo contrario es un pequeño montón superior
Idea básica
1. Construya la secuencia para clasificarla en un montón superior grande
En este momento, el valor máximo de toda la secuencia es el nodo raíz del elemento del montón.
Cámbielo con el último elemento, y el final es el valor máximo en este momento.
Luego reconstruya los n-1 elementos restantes en una pila, de modo que se obtenga el siguiente valor más pequeño de n elementos. Tal ejecución repetida resultará en una secuencia ordenada.
Diagrama
El ejemplo en el video instructivo tiene una matriz {4,6,8,5,9} usando el algoritmo de clasificación de pila
Luego comenzamos desde el último nodo no hoja (el nodo hoja naturalmente no necesita ser ajustado, el primer nodo no hoja arr.length / 2-1 = 5 / 2-1 = 1, que son los 6 nodos debajo ), Ajuste de izquierda a derecha y de abajo hacia arriba .
Luego encuentre el segundo nodo no hoja 4, encuentre que 9 elementos de 4, 9, 8 son los más grandes y que 4 y 9 se intercambian
En este momento, el intercambio provocó que la estructura de la subraíz [4, 5, 6] fuera caótica y continuara ajustándose. En [4, 5, 6], 6 es el más grande y 4 y 6 se intercambian .
Hasta ahora, nuestro gran impulso se ha completado
Segundo paso
Cambie el elemento superior con el último elemento para hacer que el último elemento sea el más grande. Luego, continúe ajustando el montón e
intercambie el elemento superior con el último elemento para obtener el segundo elemento más grande. El intercambio, la reconstrucción y el intercambio se repiten de esta manera.
9 ya no se usa para ordenar, lo trataremos como si se estuviera moviendo fuera de la matriz
Luego, reajuste la estructura para continuar cumpliendo con la definición del montón
Luego intercambie el elemento superior 8 con el último elemento 5 para obtener el segundo elemento más grande 8.
Las operaciones posteriores repiten lo anterior y finalmente obtienen una secuencia ordenada
Resumen del profesor
1. Construya la secuencia desordenada en una pila y seleccione la pila superior grande o la pila superior pequeña de acuerdo con los requisitos de orden ascendente y descendente;
2. Cambie el elemento superior con el elemento final [hundir el elemento más grande hasta el final de la matriz
3. Vuelva a ajustar la estructura para cumplir con la definición del montón, y luego continúe intercambiando el elemento superior y el elemento final actual, y repita los pasos de ajuste + intercambio hasta que toda la secuencia esté en orden.
Código
package 树;
import java.util.Arrays;
//堆排序
//2021年1月31日21:26:04
//作者 @王
public class HeapSort {
public static void main(String[] args) {
// TODO Auto-generated method stub
int arr[] ={
4,6,8,5,9};
heapSort(arr);
}
//编写堆排序的方法
public static void heapSort(int[] arr){
int temp = 0;
System.out.println("堆排序");
// //分步完成
// adjustHeap(arr, 1, arr.length);
// System.out.println("第一次调整"+Arrays.toString(arr));
// adjustHeap(arr, 0, arr.length);
// System.out.println("第二次调整"+Arrays.toString(arr));
//将我们的数组变成一个大顶堆
for (int i = arr.length/2 -1; i >=0; i--) {
adjustHeap(arr, i, arr.length);
}
//将堆顶元素与末尾元素交换,将最大元素沉到数组末端
//重新调整结构,使其满足堆定义,然后继续减缓堆顶元素与当前末尾元素,反复
//执行调整+交换步骤直到整个序列有序
for(int j = arr.length-1;j>0;j--){
//交换
temp = arr[j];
arr[j] = arr[0];
arr[0] = temp;
adjustHeap(arr, 0, j);
}
}
//将一个数组(二叉树),调整成一个大顶堆或者小顶堆
/**
* 功能:完成将以i对应的非叶子结点的树调整成大顶堆
* 举例 4,6,8,5,9 => i=1 => 得到 4,9,8,5,6
* @param arr
* @param i 表示非叶子节点在数组中的索引
* @param length 表示对多少个元素继续调整,length是在逐渐的减少
*/
public static void adjustHeap(int arr[],int i,int length){
int temp = arr[i];//取出当前元素的值,保存在临时变量
//开始调整
//1. k = i*2+1 k 是i节点的左子节点
for (int k = i * 2 +1; k < length; k = k * 2 +1) {
if(k + 1 < length && arr[k] < arr[k+1]){
//说明左子节点的值小于右子节点的值
k++;//k指向右子节点
}
if(arr[k] > temp){
//如果子节点大于父节点
arr[i] = arr[k];
i = k;//i指向K 继续循环比较
}else{
break;
}
}
//当for循环结束后,我们已经将以i为父节点的树的最大值,放在了最顶上(局部)
arr[i] = temp;
}
}