Algoritmo di ordinamento heap (con Code in Python and C++)

โšก Riepilogo intelligente

L'algoritmo Heap Sort ordina un array costruendo un heap binario e ripetendolotracinserendo il suo valore radice nella sezione ordinata. Questa risorsa spiega heapify, heap max e min, pseudocodice e completo Python and C++ implementazioni con analisi della complessitร  temporale.

  • ๐ŸŒณ Idea centrale: L'ordinamento heap crea un heap binario completo, quindi ripetutamente escluditracts la radice per produrre un ordine ordinato.
  • ๐Ÿ”บ Heapify: L'operazione heapify ripristina la proprietร  dell'heap tramite scambioping un genitore con il figlio piรน grande.
  • ๐Ÿ—ƒ๏ธ Archiviazione array: Un heap รจ memorizzato in un array in cui un nodo all'indice i ha figli agli indici 2i+1 e 2i+2.
  • ๏ธ Complessitร : L'algoritmo di ordinamento heap sort ha una complessitร  temporale di O(n log n) in tutti i casi e utilizza uno spazio aggiuntivo di O(1).
  • ๐Ÿ’ป Code Fornito: lavoro Python and C++ I programmi dimostrano heapify, la creazione di heap e l'ordinamento completo.

Cos'รจ l'algoritmo di ordinamento heap?

L'algoritmo Heap Sort รจ uno degli algoritmi di ordinamento piรน popolari e veloci. Si basa sulla struttura dati ad albero binario completo. L'obiettivo รจ trovare l'elemento massimo e posizionarlo in cima all'heap, ovvero sul nodo padre dell'albero binario.

Diciamo che viene fornito un array, dati = [10,5, 7, 9, 4, 11, 45, 17, 60].

Nell'array, se l'indice i-esimo (i=0,1,2,3 โ€ฆ) รจ un nodo genitore, allora (2i+1) e (2i+2) saranno i figli sinistro e destro. La creazione di un albero binario completo con questo array sarร  simile a questa:

Algoritmo di ordinamento dell'heap

Eseguiremo il processo heapify dall'inizio alla fine dell'array. Inizialmente, se convertiamo l'array in un albero, apparirร  come sopra. Possiamo vedere che non mantiene alcuna proprietร  heap (min-heap o max heap). Otterremo l'array ordinato eseguendo il processo heapify per tutti i nodi.

Applicazione dell'ordinamento heap

Ecco alcuni utilizzi dell'algoritmo di ordinamento dell'heap:

  • La costruzione di "code prioritarie" richiede l'ordinamento dell'heap. Perchรฉ heapsort mantiene l'elemento ordinato dopo ogni inserimento.
  • La struttura dei dati heap รจ efficiente nel trovare kth elemento piรน grande in un dato array.
  • Il kernel Linux utilizza l'ordinamento heap come impostazione predefinita algoritmo di ordinamento poichรฉ ha complessitร  spaziale O(1).

Crea ordinamento heap con l'esempio

Qui costruiremo un heap massimo dal seguente albero binario completo.

Crea ordinamento heap con l'esempio

I nodi foglia sono 17, 60, 4, 11 e 45. Non hanno alcun nodo figlio. Ecco perchรฉ sono nodi foglia. Quindi, avvieremo il metodo heapify dal loro nodo padre. Ecco i passaggi:

Passo 1) Seleziona il sottoalbero piรน a sinistra. Se i nodi figli sono maggiori, scambia il nodo genitore con il nodo figlio.

Qui il nodo genitore รจ 9. E i nodi figli sono 17 e 60. Poichรฉ 60 รจ il piรน grande, 60 e 9 verranno scambiati per mantenere il heap max.

Crea ordinamento heap con l'esempio

Passo 2) Ora, il sottoalbero piรน a sinistra รจ heapificato. Il nodo genitore successivo รจ 7. Questo nodo genitore ha due nodi figli e il piรน grande รจ 45. Quindi, 45 e 7 verranno scambiati.

Crea ordinamento heap con l'esempio

Crea ordinamento heap con l'esempio

Passo 3) I nodi 60 e 4 hanno il nodo genitore 5. Poichรฉ โ€œ5โ€ รจ piรน piccolo del nodo figlio 60, verrร  scambiato.

Crea ordinamento heap con l'esempio

Crea ordinamento heap con l'esempio

Passo 4) Ora, il nodo 5 ha il nodo figlio 17,9. Ciรฒ non mantiene la proprietร  heap massima. Quindi, 5 verrร  sostituito con 17.

Crea ordinamento heap con l'esempio

Passo 5) Il nodo 10 verrร  scambiato con 60, quindi con 17. Il processo sarร  simile al seguente.

Crea ordinamento heap con l'esempio

Crea ordinamento heap con l'esempio

Passo 6) Fino al passaggio 5 abbiamo creato l'heap massimo. Ogni nodo genitore รจ piรน grande dei suoi nodi figli. Il nodo radice ha il valore massimo (60).

Nota: Per creare l'array ordinato, dobbiamo sostituire il nodo con valore massimo con il suo successore.

Questo processo si chiama "extract maxโ€. Poichรฉ 60 รจ il nodo massimo, fisseremo la sua posizione sull'indice 0 e creeremo l'heap senza il nodo 60.

Crea ordinamento heap con l'esempio

Crea ordinamento heap con l'esempio

Passo 7) Poichรฉ 60 viene rimosso, il valore massimo successivo รจ 45. Eseguiremo il processo โ€œExtract Maxโ€ di nuovo dal nodo 45.

Questa volta otterremo 45 e sostituiremo il nodo radice con il suo successore 17.

Dobbiamo esibirciโ€Extract Max" finchรฉ tutti gli elementi non saranno ordinati.

Dopo aver eseguito questi passaggi fino a quando non saremotracImpostando tutti i valori massimi, otterremo il seguente array.

Crea ordinamento heap con l'esempio

Cos'รจ l'heap binario?

Un heap binario รจ una sorta di completo albero binario struttura dati. In questo tipo di struttura ad albero, il nodo genitore รจ maggiore o minore dei nodi figli. Se il nodo genitore รจ piรน piccolo, l'heap รจ chiamato "Min Heap" e se il nodo genitore รจ piรน grande, l'heap รจ chiamato "Max Heap".

Ecco alcuni esempi di heap minimo e heap massimo.

Heap minimo e Heap massimo
Heap minimo e Heap massimo

Nella figura sopra, se noti il โ€‹โ€‹"Min Heap", il nodo genitore รจ sempre piรน piccolo dei suoi nodi figli. In cima all'albero troviamo il valore piรน piccolo, 10.

Allo stesso modo, per il "Max Heap", il nodo genitore รจ sempre piรน grande dei nodi figli. L'elemento massimo รจ presente nel nodo head per il "Max Heap".

Che cosa รจ โ€œHeapifyโ€?

"Heapify" รจ il principio dell'heap che assicura la posizione del nodo. In Heapify, un heap massimo mantiene sempre una relazione con il padre e il figlio, e cioรจ il nodo padre sarร  piรน grande dei nodi figlio.

Ad esempio, se viene aggiunto un nuovo nodo, dobbiamo rimodellare l'heap. Tuttavia, potremmo dover cambiare o scambiare i nodi o riorganizzare l'array. Questo processo di rimodellamentoping un heap viene chiamato โ€œheapifyโ€.

Ecco un esempio di come funziona heapify:

Aggiunta di un nuovo nodo e Heapify
Aggiungere un nuovo nodo e heapify

Ecco i passaggi per heapify:

Passo 1) Aggiunto il nodo 65 come figlio destro del nodo 60.

Passo 2) Controlla se il nodo appena aggiunto รจ maggiore del genitore.

Passo 3) Poichรฉ รจ piรน grande del nodo genitore, abbiamo scambiato il figlio destro con il suo genitore.

Come costruire l'heap

Prima di costruire l'heap o di heapificare un albero, dobbiamo sapere come lo memorizzeremo. Poichรฉ l'heap รจ un albero binario completo, รจ meglio usare un schieramento per contenere i dati dell'heap.

Diciamo che un array contiene un totale di n elementi. Se l'indice "i" รจ un nodo genitore, il nodo sinistro sarร  all'indice (2i+1)e il nodo destro sarร  in indice (2i+2). Supponiamo che l'indice dell'array inizi da 0.

Utilizzando questo, memorizziamo un heap massimo in un array simile al seguente:

Rappresentazione basata su array dell'heap massimo
Rappresentazione basata su array dell'heap massimo

L'algoritmo heapify mantiene la proprietร  heap. Se il genitore non ha il valore estremo (piรน piccolo o piรน grande), verrร  scambiato con il nodo figlio piรน estremo.

Ecco i passaggi per heapizzare un heap massimo:

Passo 1) Inizia dal nodo foglia.

Passo 2) Trova il massimo tra genitore e figli.

Passo 3) Scambia i nodi se il nodo figlio ha un valore maggiore del genitore.

Passo 4) Sali di un livello.

Passo 5) Segui i passaggi 2,3,4 fino a raggiungere l'indice 0 o ordinare l'intero albero.

Ecco lo pseudo-codice per heapify ricorsivo (heap massimo):

def heapify():
  inputโ†’ array, size, i
  largest = i
  left = 2*i + 1
  right = 2*i + 2
if left<n and array[largest ] < array[left]:
  largest = left
if right<n and array[largest ] < array[right]:
  largest = right
If largest not equals i:
  swap(array[i],array[largest])
  heapify(array,n,largest)

Soprannome Code per l'ordinamento Heap

Ecco lo pseudo-codice per l'algoritmo di ordinamento dell'heap:

Heapify(numbers as an array, n as integer, i as integer):
  largest = i
  left = 2i+1
  right= 2i+2
if(left<=n) and (numbers[i]<numbers[left])
  largest=left
if(right<=n) and (numbers[i]<numbers[right])
  largest=right
if(largest  != i)
  swap(numbers[i], numbers[largest])
  Heapify(numbers,n,largest)
HeapSort(numbers as an array):
  n= numbers.size()
for i in range n/2 to 1
  Heapify(numbers,n,i)
for i in range n to 2
  Swap numbers[i] with numbers[1]
  Heapify(numbers,i,0)

Esempio di ordinamento Heap Code in C++

#include <iostream>
using namespace std;
void display(int arr[], int n)
{
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << "\t";
    }
    cout << endl;
}
void heapify(int numbers[], int n, int i)
{
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    if (left < n && numbers[left] < numbers[largest])
    {
        largest = left;
    }
    if (right < n && numbers[right] < numbers[largest])
    {
        largest = right;
    }
    if (largest != i)
    {
	//uncomment the following line to see details in output
        //cout<<"Swapping "<< numbers[i]<< " and "<<numbers[largest]<<endl;
        swap(numbers[i], numbers[largest]);
        heapify(numbers, n, largest);
    }
}
void heapSort(int numbers[], int n)
{
    for (int i = n/2 - 1; i >= 0; i--)
    {
        heapify(numbers, n, i);
//uncomment the following line to see details in output
 //cout<<"Heapify:\t";
  //display(numbers,n);
    }
    for (int i = n - 1; i >= 0; i--)
    {
        swap(numbers[0], numbers[i]);
        heapify(numbers, i, 0);
    }
}
int main()
{
    int numbers[] = { 10,5, 7, 9, 4, 11, 45, 17, 60};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    cout<<"Initial Array:\t";
    display(numbers,size);
    heapSort(numbers, size);
    cout<<"Sorted Array (descending order):\t";
    display(numbers, size);
}

Produzione:

Initial Array:  10      5       7       9       4       11      45      17      60
Sorted Array (descending order):  60      45      17      11      10      9       7       5       4

Esempio di ordinamento Heap Code in Python

def display(arr):
    for i in range(len(arr)):
    print(arr[i], end = "\t")
print()
def heapify(numbers, n, i):
    largest = i
left = 2 * i + 1
right = 2 * i + 2
if left < n and numbers[left] < numbers[largest]:
    largest = left
if right < n and numbers[right] < numbers[largest]:
    largest = right
if largest != i:
    numbers[i], numbers[largest] = numbers[largest], numbers[i]
heapify(numbers, n, largest)
def heapSort(items, n):
    for i in range(n //2,-1,-1):
        heapify(items, n, i) for i in range(n - 1, -1, -1):
        items[0], items[i] = items[i], items[0] heapify(items, i, 0) numbers = [10, 5, 7, 9, 4, 11, 45, 17, 60] print("Initial List:\t", end = "") display(numbers) print("After HeapSort:\t", end = "") heapSort(numbers, len(numbers)) display(numbers)

Produzione:

Initial List:   10      5       7       9       4       11      45      17      60
After HeapSort: 60      45      17      11      10      9       7       5       4

Analisi della complessitร  temporale e spaziale di Heap Sort

Ci sono complessitร  temporale e complessitร  spaziale che possiamo analizzare per l'ordinamento heap. Per la complessitร  temporale abbiamo i seguenti casi:

  1. Caso migliore
  2. Caso medio
  3. Caso peggiore

L'heap รจ implementato su un albero binario completo. Quindi, al livello piรน basso dell'albero binario, ci sarร  il numero massimo di nodi. Se il livello inferiore ha n nodi, il livello superiore avrร  n/2 nodi.

Analisi della complessitร  temporale e spaziale

In questo esempio, il livello 3 ha quattro elementi, il livello 2 ha due elementi e il livello 1 ha un elemento. Se รจ presente un numero totale di n elementi, l'altezza o il livello totale sarร  Log2(N). Pertanto, l'inserimento di un singolo elemento potrebbe richiedere un massimo di iterazioni Log(n).

Quando vogliamo prendere il valore massimo dall'heap, prendiamo semplicemente il nodo radice. Poi, eseguiamo di nuovo heapify. Ogni heapify prende Log2(N) tempo. Es.tractrovare il massimo richiede un tempo O(1).

migliori Complessitร  temporale del caso per l'algoritmo di ordinamento heap

Quando tutti gli elementi sono giร  ordinati nell'array, ci vorrร  O(n) tempo per costruire l'heap. Perchรฉ se l'elenco รจ ordinato, l'inserimento di un elemento richiederร  il tempo costante O(1).

Quindi, nel migliore dei casi, ci vorrร  O (n) tempo per creare un heap massimo o minimo.

Complessitร  temporale media del caso per l'algoritmo di ordinamento heap

Inserimento di un elemento o extraccalcolare un massimo richiede un tempo O(log(n)). Quindi, la complessitร  temporale media per l'algoritmo di ordinamento heap รจ O(nlog(n)).

Complessitร  temporale del caso peggiore per l'algoritmo di ordinamento heap

Similmente al caso medio, nello scenario peggiore, potremmo eseguire heapify n volte. Ogni heapify costerร  O(log(n)) di tempo. Quindi, la complessitร  temporale del caso peggiore sarร  O(nlog(n)).

Complessitร  spaziale per l'algoritmo di ordinamento heap

Heap sort รจ un algoritmo progettato in loco. Ciรฒ significa che non รจ necessaria memoria extra o temporanea per eseguire l'attivitร . Se osserviamo l'implementazione, noteremo che abbiamo utilizzato swap() per eseguire lo scambio dei nodi. Non รจ stato necessario nessun altro elenco o array. Quindi, la complessitร  dello spazio รจ O(1).

DOMANDE FREQUENTI

L'ordinamento heap non รจ un algoritmo di ordinamento stabile, perchรฉ la costruzione e l'esportazionetracL'estrazione di dati dall'heap puรฒ riordinare gli elementi uguali. Se รจ importante preservare l'ordine originale delle chiavi uguali, un algoritmo stabile come il merge sort รจ una scelta migliore.

L'ordinamento heap garantisce una complessitร  temporale di O(n log n) in tutti i casi e utilizza uno spazio aggiuntivo di O(1). Il quicksort รจ solitamente piรน veloce nella pratica, ma puรฒ degradare a O(nยฒ) in presenza di pivot non ottimali. L'ordinamento heap sacrifica un po' di velocitร  per garantire un'affidabilitร  maggiore nel caso peggiore.

Sia l'heap sort che il merge sort hanno una complessitร  temporale di O(n log n). L'heap sort ordina sul posto con uno spazio aggiuntivo di O(1), ma รจ instabile. Il merge sort รจ stabile, ma necessita di uno spazio aggiuntivo di O(n) per l'unione.

I tutor IA possono animare il processo di heapify, mostrare come si forma l'heap massimo e trace ciascunotracPasso t-max. Questo aiuto visivo e interattivo facilita la comprensione, anche per i principianti, di come l'algoritmo di ordinamento heap ordina un array.

Sรฌ. Gli assistenti di programmazione basati sull'IA possono tradurre un'implementazione di ordinamento heap tra linguaggi come C++, Pythone Java mentre mantieniping la logica รจ rimasta intatta. Dovresti comunque compilare e testare il codice convertito per confermare la correttezza dell'output.

Riassumi questo post con: