Arquitetura de dados e algoritmo-C / C ++ para alcançar o algoritmo de classificação Heap [coleção recomendada]

Um, introdução de classificação de heap

Heap Sort (Heap Sort) refere-se a um algoritmo de classificação projetado usando a estrutura de dados do heap.
Portanto, antes de aprender a classificar heap, é necessário entender o heap! Se os leitores não estiverem familiarizados com heaps, é recomendado entender heaps primeiro (é recomendado entendê-los por meio de artigos como heap binário, heap inclinado para a esquerda, heap oblíquo, heap binomial ou heap Fibonacci, etc.) e, em seguida, estudar este capítulo.

Sabemos que a pilha é dividida em "a maior pilha" e "a menor pilha". O maior heap é normalmente usado para classificação "ascendente" e o menor heap é geralmente usado para classificação "decrescente".
Tendo em vista a relação simétrica entre o maior heap e o menor heap, basta entender um deles. Este artigo fornecerá uma descrição detalhada da classificação crescente implementada pelo heap máximo.

A ideia básica da classificação do maior heap em ordem crescente:
① Inicializar o heap: Construa a sequência a [1 ... n] no maior heap.
② Trocar dados: troque a [1] e a [n] de modo que a [n] seja o valor máximo em [1 ... n]; em seguida, reajuste a [1 ... n-1] para o heap máximo . Em seguida, troque a [1] e a [n-1] para que a [n-1] seja o valor máximo em [1 ... n-1]; em seguida, reajuste a [1 ... n-2] para o valor máximo. E assim por diante, até que toda a sequência esteja em ordem.

A seguir, analisaremos o processo de implementação da classificação de heap por meio de gráficos e texto. Observe que "a natureza do heap binário implementado pela matriz" é usada na implementação.
No caso em que o índice do primeiro elemento é 0:
Propriedade 1: O índice do filho esquerdo com índice i
é (2 i + 1); Propriedade 2: O índice do filho esquerdo com índice i é (2 i + 2);
Propriedade 3: O índice do nó pai com índice i é floor ((i-1) / 2);
Insira a descrição da imagem aqui
Por exemplo, para a maior pilha {110,100,90,40,80,20,60,10,30 , 50,70} Em termos de: o filho esquerdo com índice 0 é todo 1; o filho direito com índice 0 é 2; o nó pai com índice 8 é 3.

Dois, descrição gráfica de classificação de heap

Código de classificação de heap (crescente)

/* 
 * (最大)堆的向下调整算法
 *
 * 注:数组实现的堆中,第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);
    }
}

A função de heap_sort_asc (a, n) é classificar a matriz a em ordem crescente; onde a é a matriz en é o comprimento da matriz.
A operação de heap_sort_asc (a, n) é dividida em duas partes: inicialização do heap e troca de dados.
maxheap_down (a, início, fim) é o algoritmo de ajuste para baixo do heap máximo.

O seguinte demonstra o processo de classificação de heap de heap_sort_asc (a, n) em a = {20,30,90,40,70,110,60,10,100,50,80}, n = 11. A seguir está a estrutura de inicialização correspondente ao array a:
Insira a descrição da imagem aqui
1 Inicialize o heap

No algoritmo de classificação de heap, a matriz a ser classificada é primeiro convertida em um heap binário.
O seguinte demonstra as etapas para converter a matriz {20,30,90,40,70,110,60,10,100,50,80} para a maior pilha {110,100,90,40,80,20,60,10,30,50 , 70}.

1,1 i = 11 / 2-1, ou seja, i = 4 O
Insira a descrição da imagem aqui
acima é o processo de ajuste de maxheap_down (a, 4, 9). A função de maxheap_down (a, 4, 9) é regular para baixo a [4 ... 9]; o filho esquerdo de a [4] é a [9] e o filho direito é a [10]. Ao ajustar, escolha o maior dos filhos esquerdo e direito (ou seja, a [10]) e troque a [4].

1.2 i = 3 O
Insira a descrição da imagem aqui
acima é o processo de ajuste maxheap_down (a, 3, 9). A função de maxheap_down (a, 3, 9) é regular para baixo a [3 ... 9]; o filho esquerdo de a [3] é a [7] e o filho direito é a [8]. Ao ajustar, escolha o maior dos filhos esquerdo e direito (ou seja, a [8]) e troque a [4].

1.3 i = 2 O
Insira a descrição da imagem aqui
acima é o processo de ajuste maxheap_down (a, 2, 9). A função de maxheap_down (a, 2, 9) é regular para baixo a [2… 9]; o filho esquerdo de a [2] é a [5] e o filho direito é a [6]. Ao ajustar, escolha o maior dos filhos esquerdo e direito (ou seja, a [5]) e troque a [2].

1.4 O
Insira a descrição da imagem aqui
acima i = 1 é o processo de ajuste de maxheap_down (a, 1, 9). A função de maxheap_down (a, 1, 9) é regular para baixo a [1 ... 9]; o filho esquerdo de a [1] é a [3] e o filho direito é a [4]. Ao ajustar, escolha o maior dos filhos esquerdo e direito (ou seja, a [3]) e troque a [1]. Após a troca, a [3] é 30, que é maior que seu filho direito a [8], e então eles são trocados.

1.5 i = 0 O
Insira a descrição da imagem aqui
acima é o processo de ajuste maxheap_down (a, 0, 9). A função de maxheap_down (a, 0, 9) é regular para baixo a [0… 9]; o filho esquerdo de a [0] é a [1] e o filho direito é a [2]. Ao ajustar, escolha o maior dos filhos esquerdo e direito (ou seja, a [2]) e troque a [0]. Após a troca, a [2] é 20, que é maior que seus filhos direito e esquerdo. Escolha o filho mais velho (ou seja, o filho esquerdo) para trocar com um [2].

Após a conclusão do ajuste, o heap máximo é obtido. Neste momento, a matriz {20,30,90,40,70,110,60,10,100,50,80} também se torna {110,100,90,40,80,20,60,10,30,50,70}.

Parte 2 Troca de dados

Depois que o array é convertido no maior heap, os dados são trocados, de modo que o array se torna um array ordenado verdadeiro.
A parte de troca de dados é relativamente simples.O seguinte é apenas um diagrama esquemático de colocar o valor máximo no final da matriz.
Insira a descrição da imagem aqui
O acima é um diagrama esquemático de troca de dados quando n = 10.
Quando n = 10, primeiro troque a [0] e a [10] de modo que a [10] seja o valor máximo entre a [0… 10]; em seguida, ajuste a [0… 9] para torná-lo o heap máximo. Após a troca: um [10] está em ordem!
Quando n = 9, primeiro troque a [0] e a [9] para que a [9] seja o valor máximo entre a [0 ... 9]; em seguida, ajuste a [0 ... 8] para torná-lo o heap máximo. Depois da troca: um [9 ... 10] está em ordem!
… E
assim por diante, até que um [0… 10] esteja em ordem.

O editor recomenda meu próprio grupo de intercâmbio de tecnologia de linguagem linuxC / C ++: [ 1106675687 ] Compilei alguns livros didáticos e materiais de vídeo que acho melhores para compartilhar nos arquivos do grupo e você pode adicioná-los se precisar deles!
Insira a descrição da imagem aqui

Terceiro, a complexidade de tempo e estabilidade da classificação de heap

Complexidade de tempo de
classificação de heap A complexidade de tempo de classificação de heap é O (N lgN). Suponha que haja N números na sequência sendo classificada. A complexidade de tempo da travessia é O (N). Quantas travessias são necessárias?
A classificação de heap é classificada usando um heap binário. Um heap binário é uma árvore binária. O número de vezes que ele precisa percorrer é a profundidade da árvore binária. De acordo com a definição de uma árvore binária completa, sua profundidade é de pelo menos lg ( N + 1). Qual é o máximo? Visto que a pilha binária é uma árvore binária completa, sua profundidade não excederá lg (2N) no máximo. Portanto, a complexidade de tempo da travessia é O (N), e o número de travessias está entre lg (N + 1) e lg (2N); portanto, sua complexidade de tempo é O (N
lgN).

Estabilidade de
classificação de heap A classificação de heap é um algoritmo instável, que não satisfaz a definição de um algoritmo estável. Quando ele troca dados, ele compara os dados entre o nó pai e o nó filho, portanto, mesmo que haja dois nós irmãos com valores iguais, sua ordem relativa pode mudar na classificação.
Estabilidade do algoritmo - suponha que haja a [i] = a [j] na sequência, se antes da classificação, a [i] está antes de a [j]; e após a classificação, a [i] ainda está antes de a [j]. Então, esse algoritmo de classificação é estável!

Quatro, implementação de classificação de heap

Três implementações de classificação de heap são fornecidas a seguir: C, C ++ e Java. Os princípios e resultados de saída dessas três implementações são os mesmos. Cada implementação inclui "ordem crescente para o maior heap" e "ordem decrescente para o menor heap".
Implementação C de classificação de heap
实现代码(heap_sort.c)

 View Code

Implementação C ++ de classificação de heap
实现代码(HeapSort.cpp)

View Code

Implementação Java de classificação de heap
实现代码(HeapSort.java)

View Code

Sua produção:

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 

Acho que você gosta

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