Arquitectura de datos y algoritmo-C / C ++ para lograr el algoritmo de clasificación de montón [Colección recomendada]

Uno, introducción al tipo de pila

Heap Sort (clasificación de montón) se refiere a un algoritmo de clasificación diseñado utilizando la estructura de datos del montón.
Por lo tanto, antes de aprender a ordenar el montón, ¡es necesario comprender el montón! Si los lectores no están familiarizados con los montones, se recomienda entenderlos primero (se recomienda entenderlos a través de artículos como montón binario, montón inclinado hacia la izquierda, montón oblicuo, montón binomial o montón de Fibonacci, etc.) y luego estudiar Este capítulo.

Sabemos que el montón se divide en "el montón más grande" y "el montón más pequeño". El montón más grande se utiliza normalmente para la clasificación "ascendente" y el montón más pequeño se utiliza normalmente para la clasificación "descendente".
En vista de la relación simétrica entre el montón más grande y el más pequeño, solo comprenda uno de ellos. Este artículo dará una descripción detallada de la ordenación ascendente implementada por el montón máximo.

La idea básica de la clasificación del montón más grande en orden ascendente:
① Inicializar el montón: Construya la secuencia a [1 ... n] en el montón más grande.
② Intercambiar datos: intercambie a [1] y a [n] para que a [n] sea el valor máximo en a [1 ... n]; luego reajuste a [1 ... n-1] al montón máximo . Luego, intercambie a [1] y a [n-1] de modo que a [n-1] sea el valor máximo en a [1 ... n-1]; luego reajuste un [1 ... n-2] al valor máximo. Y así sucesivamente, hasta que toda la secuencia esté en orden.

A continuación, analizaremos el proceso de implementación de la clasificación de montón a través de gráficos y texto. Tenga en cuenta que "la naturaleza del montón binario implementado por la matriz" se utiliza en la implementación.
En el caso donde el índice del primer elemento es 0:
Propiedad 1: El índice del niño izquierdo con índice i
es (2 i + 1); Propiedad 2: El índice del niño izquierdo con índice i es (2 i + 2);
Propiedad 3: El índice del nodo principal con índice i es el piso ((i-1) / 2);
Inserte la descripción de la imagen aquí
Por ejemplo, para el montón más grande {110,100,90,40,80,20,60,10,30 , 50,70} En términos de: el hijo izquierdo con índice 0 es todo 1; el hijo derecho con índice 0 es 2; el nodo padre con índice 8 es 3.

Dos, Descripción gráfica de clasificación de montón

Código de clasificación de montón (ascendente)

/* 
 * (最大)堆的向下调整算法
 *
 * 注:数组实现的堆中,第N个节点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)。
 *     其中,N为数组下标索引值,如数组中第1个数对应的N为0。
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     start -- 被下调节点的起始位置(一般为0,表示从第1个开始)
 *     end   -- 截至范围(一般为数组中最后一个元素的索引)
 */
void maxheap_down(int a[], int start, int end)
{
    
    
    int c = start;            // 当前(current)节点的位置
    int l = 2*c + 1;        // 左(left)孩子的位置
    int tmp = a[c];            // 当前(current)节点的大小
    for (; l <= end; c=l,l=2*l+1)
    {
    
    
        // "l"是左孩子,"l+1"是右孩子
        if ( l < end && a[l] < a[l+1])
            l++;        // 左右两孩子中选择较大者,即m_heap[l+1]
        if (tmp >= a[l])
            break;        // 调整结束
        else            // 交换值
        {
    
    
            a[c] = a[l];
            a[l]= tmp;
        }
    }
}

/*
 * 堆排序(从小到大)
 *
 * 参数说明:
 *     a -- 待排序的数组
 *     n -- 数组的长度
 */
void heap_sort_asc(int a[], int n)
{
    
    
    int i;

    // 从(n/2-1) --> 0逐次遍历。遍历之后,得到的数组实际上是一个(最大)二叉堆。
    for (i = n / 2 - 1; i >= 0; i--)
        maxheap_down(a, i, n-1);

    // 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素
    for (i = n - 1; i > 0; i--)
    {
    
    
        // 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。
        swap(a[0], a[i]);
        // 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。
        // 即,保证a[i-1]是a[0...i-1]中的最大值。
        maxheap_down(a, 0, i-1);
    }
}

La función de heap_sort_asc (a, n) es ordenar la matriz a en orden ascendente; donde a es la matriz yn es la longitud de la matriz.
La operación de heap_sort_asc (a, n) se divide en dos partes: inicializar el montón e intercambiar datos.
maxheap_down (a, start, end) es el algoritmo de ajuste hacia abajo del montón máximo.

A continuación, se muestra el proceso de ordenación del montón de heap_sort_asc (a, n) en a = {20,30,90,40,70,110,60,10,100,50,80}, n = 11. La siguiente es la estructura de inicialización correspondiente a la matriz a:
Inserte la descripción de la imagen aquí
1 Inicializar el montón

En el algoritmo de ordenación del montón, la matriz que se va a ordenar se convierte primero en un montón binario.
A continuación, se muestran los pasos para convertir la matriz {20,30,90,40,70,110,60,10,100,50,80} en el montón más grande {110,100,90,40,80,20,60,10,30,50 , 70}.

1.1 i = 11 / 2-1, es decir, i = 4 Lo
Inserte la descripción de la imagen aquí
anterior es el proceso de ajuste de maxheap_down (a, 4, 9). La función de maxheap_down (a, 4, 9) es regular a la baja un [4 ... 9], el hijo izquierdo de un [4] es un [9] y el hijo derecho es un [10]. Al ajustar, elija el más grande de los hijos izquierdo y derecho (es decir, un [10]) e intercambie un [4].

1.2 i = 3 Lo
Inserte la descripción de la imagen aquí
anterior es el proceso de ajuste maxheap_down (a, 3, 9). La función de maxheap_down (a, 3, 9) es regular a la baja un [3 ... 9], el hijo izquierdo de un [3] es un [7] y el hijo derecho es un [8]. Al ajustar, elija el más grande de los hijos izquierdo y derecho (es decir, un [8]) e intercambie un [4].

1.3 i = 2 Lo
Inserte la descripción de la imagen aquí
anterior es el proceso de ajuste maxheap_down (a, 2, 9). La función de maxheap_down (a, 2, 9) es regular a la baja un [2… 9], el hijo izquierdo de un [2] es un [5] y el hijo derecho es un [6]. Al ajustar, elija el más grande de los hijos izquierdo y derecho (es decir, un [5]) y cambie un [2].

1.4 El i = 1 anterior
Inserte la descripción de la imagen aquí
es el proceso de ajuste de maxheap_down (a, 1, 9). La función de maxheap_down (a, 1, 9) es regular a la baja un [1 ... 9], el hijo izquierdo de un [1] es un [3] y el hijo derecho es un [4]. Al ajustar, elija el más grande de los hijos izquierdo y derecho (es decir, un [3]) e intercambie un [1]. Después del intercambio, a [3] es 30, que es más grande que su hijo derecho a [8], y luego se intercambian.

1.5 i = 0 Lo
Inserte la descripción de la imagen aquí
anterior es el proceso de ajuste maxheap_down (a, 0, 9). La función de maxheap_down (a, 0, 9) es regular a la baja un [0… 9], el hijo izquierdo de un [0] es un [1] y el hijo derecho es un [2]. Al ajustar, elija el más grande de los hijos izquierdo y derecho (es decir, un [2]) e intercambie un [0]. Después del intercambio, un [2] es 20, que es más grande que sus hijos izquierdo y derecho. Elija al niño mayor (es decir, el hijo izquierdo) para intercambiar con un [2].

Una vez completado el ajuste, se obtiene el montón máximo. En este momento, la matriz {20,30,90,40,70,110,60,10,100,50,80} también se convierte en {110,100,90,40,80,20,60,10,30,50,70}.

Parte 2 Intercambiar datos

Una vez que la matriz se convierte en el montón más grande, los datos se intercambian, de modo que la matriz se convierte en una verdadera matriz ordenada.
La parte de intercambio de datos es relativamente simple, el siguiente es sólo un diagrama esquemático de colocar el valor máximo al final de la matriz.
Inserte la descripción de la imagen aquí
Lo anterior es un diagrama esquemático del intercambio de datos cuando n = 10.
Cuando n = 10, primero intercambie un [0] y un [10] de modo que a [10] sea el valor máximo entre un [0… 10], luego, ajuste un [0… 9] para convertirlo en el montón máximo. Después del intercambio: ¡un [10] está en orden!
Cuando n = 9, primero intercambie un [0] y un [9] para que un [9] sea el valor máximo entre un [0… 9], luego ajuste un [0… 8] para convertirlo en el montón máximo. Después del intercambio: ¡un [9 ... 10] está en orden!
… Y
así sucesivamente, hasta que un [0… 10] esté en orden.

El editor recomienda mi propio grupo de intercambio de tecnología de lenguaje linuxC / C ++: [ 1106675687 ] He recopilado algunos libros de aprendizaje y materiales de video que creo que es mejor compartir en los archivos del grupo, ¡y puede agregarlos si los necesita!
Inserte la descripción de la imagen aquí

En tercer lugar, la complejidad del tiempo y la estabilidad del tipo de pila

Complejidad de tiempo de
clasificación de montón La complejidad de tiempo de clasificación de montón es O (N lgN). Suponga que hay N números en la secuencia que se ordena. La complejidad temporal del recorrido es O (N). ¿Cuántos recorridos se necesitan?
La clasificación de montón se ordena mediante un montón binario. Un montón binario es un árbol binario. El número de veces que necesita atravesar es la profundidad del árbol binario. Según la definición de un árbol binario completo, su profundidad es al menos lg ( N + 1). ¿Cuál es el máximo? Dado que el montón binario es un árbol binario completo, su profundidad no excederá lg (2N) como máximo. Por lo tanto, la complejidad temporal del recorrido es O (N) y el número de recorrido está entre lg (N + 1) y lg (2N); por lo tanto, su complejidad temporal es O (N
lgN).

Estabilidad de
ordenación de pila La ordenación de pila es un algoritmo inestable, que no satisface la definición de un algoritmo estable. Cuando intercambia datos, compara los datos entre el nodo padre y el nodo hijo, por lo tanto, incluso si hay dos nodos hermanos con valores iguales, su orden relativo puede cambiar en la clasificación.
Estabilidad del algoritmo: suponga que hay a [i] = a [j] en la secuencia, si antes de ordenar, a [i] está antes de a [j], y después de ordenar, a [i] todavía está antes de a [j]. ¡Entonces este algoritmo de clasificación es estable!

Cuatro, implementación de ordenación del montón

A continuación se muestran tres implementaciones de ordenación de pila: C, C ++ y Java. Los principios y los resultados de salida de estas tres implementaciones son los mismos. Cada implementación incluye "orden ascendente para el montón más grande" y "orden descendente para el montón más pequeño".
Implementación de C de ordenación de montón
实现代码(heap_sort.c)

 View Code

Implementación de C ++ de clasificación de montón
实现代码(HeapSort.cpp)

View Code

Implementación de Java de clasificación de montón
实现代码(HeapSort.java)

View Code

Su salida:

before sort:20 30 90 40 70 110 60 10 100 50 80 
after  sort:10 20 30 40 50 60 70 80 90 100 110 

Supongo que te gusta

Origin blog.csdn.net/m0_50662680/article/details/113052057
Recomendado
Clasificación