Algoritmo di ordinamento per inserimento con C, C++, Java, Python Esempi

โšก Riepilogo intelligente

L'ordinamento per inserimento รจ un metodo di ordinamento in loco basato sul confronto che costruisce una lista ordinata un elemento alla volta. รˆ stabile, adattabile, semplice da implementare e, nella pratica, si adatta bene a set di dati di piccole dimensioni o quasi ordinati.

  • ๐Ÿ“ฅ Idea centrale: L'algoritmo di ordinamento per inserimento seleziona ogni elemento e lo sposta a sinistra finchรฉ non si trova nella posizione corretta all'interno della sottolista giร  ordinata.
  • ๐Ÿ” inserire Operazione: L'algoritmo si basa su ripetuti confronti di scambio con sinistra, che aumentano la regione ordinata di un elemento per ogni passaggio del ciclo esterno.
  • โšก Complessitร  temporale: Il caso migliore richiede una complessitร  temporale di O(n) per dati giร  ordinati, mentre i casi peggiore e medio raggiungono O(n^2) per input invertiti o mescolati.
  • โœ… Proprietร : L'algoritmo รจ online, in loco, stabile e adattivo, il che lo rende prevedibile per inserimenti in streaming e array parzialmente ordinati.
  • ๐Ÿงช Code Copertura: Le implementazioni di riferimento sono fornite in C, C++e Python in modo che gli studenti possano confrontare le strutture dei cicli e i meccanismi di scambio fianco a fianco.
  • ๐Ÿค– Angolo dell'IA: I moderni assistenti basati sull'intelligenza artificiale visualizzano i passaggi dell'algoritmo di ordinamento per inserimento e lo raccomandano quando gli array di input sono corti o quasi ordinati.

Cos'รจ l'ordinamento per inserzione?

L'ordinamento per inserimento รจ uno degli algoritmi di ordinamento per confronto utilizzati per ordinare gli elementi iterando su un elemento alla volta e posizionandolo nella sua posizione corretta all'interno di una regione giร  ordinata.

Ciascun elemento viene inserito sequenzialmente in una lista giร  ordinata. La dimensione iniziale della lista giร  ordinata รจ uno. L'algoritmo di ordinamento per inserimento garantisce che i primi k elementi siano ordinati dopo la k-esima iterazione del ciclo esterno.

Poichรฉ l'algoritmo Insertion Sort costruisce il risultato in modo incrementale, รจ intuitivo da insegnare, facile da sottoporre a debug e rappresenta un'ottima base di partenza per input molto piccoli, dove algoritmi piรน complessi aggiungerebbero un sovraccarico senza vantaggi misurabili.

Caratteristiche dell'algoritmo di ordinamento per inserzione

L'algoritmo di ordinamento per inserimento presenta le seguenti caratteristiche importanti che ne spiegano il comportamento su carichi di lavoro reali:

  • รˆ una tecnica di ordinamento stabile, quindi non modifica l'ordine relativo degli elementi uguali.
  • รˆ efficiente per insiemi di dati di piccole dimensioni, ma non efficace per elenchi piรน lunghi dove prevale la crescita quadratica.
  • L'ordinamento per inserimento รจ adattivo, ovvero riduce il numero totale di passaggi se l'input รจ parzialmente ordinato. Italia viene fornito come input per renderlo efficiente poichรฉ l'accesso casuale consente spostamenti a tempo costante durante il ciclo interno.
  • Si tratta di un algoritmo in loco, quindi non richiede memoria ausiliaria proporzionale alla dimensione dell'input.

Tenendo presenti queste caratteristiche, la sezione successiva illustra l'operazione di inserimento fondamentale che alimenta ogni passaggio dell'algoritmo.

Come funziona Insert Operalavoro?

Nell'algoritmo Insertion Sort, l'operazione di inserimento viene utilizzata per ordinare gli elementi non ordinati. Consente di inserire un nuovo elemento in un elenco giร  ordinato, preservando l'ordine esistente della regione ordinata.

Pseudocodice dell'operazione di inserimento:

Consideriamo una lista A di N elementi.

// Insert A[N-1] into sorted sublist A[0..N-2]
for i = N-1 to 1:
    if A[i] < A[i-1], then swap A[i] and A[i-1]
    else stop

inserire Operalavoro di zione

Nell'esempio precedente, un nuovo elemento 6 viene inserito in un elenco giร  ordinato. I passaggi seguenti trace il ciclo interno mentre il nuovo elemento migra verso sinistra, in direzione della sua posizione corretta.

Passo 1) Rispetto all'elemento adiacente sinistro di A[5], 9 > 6, invertiamo la posizione di 9 e 6. Ora l'elemento 6 viene spostato in A[4].

Passo 2) Ora confrontiamo A[4] e A[3] e scopriamo che A[3] > A[4], quindi scambiamo di nuovo la posizione di 6 e 8.

Passo 3) Ora confrontiamo A[3] e A[2]. Poichรฉ A[2] > A[3], scambiamo la posizione di 7 e 6.

Passo 4) Confrontiamo A[1] e A[2]. Poichรฉ A[1] < A[2], l'elemento adiacente a sinistra non รจ piรน maggiore. Concludiamo che 6 รจ stato inserito correttamente e interrompiamo il ciclo interno qui.

Come funziona l'ordinamento per inserimento

L'operazione di inserimento descritta sopra รจ la base dell'algoritmo di ordinamento per inserimento (Insertion Sort). La procedura di inserimento viene eseguita su ogni elemento e, alla fine, si ottiene la lista ordinata, poichรฉ la regione ordinata si espande di un elemento a ogni passaggio verso l'esterno.

L'ordinamento per inserimento funziona

La figura sopra illustra il funzionamento dell'algoritmo di ordinamento per inserimento (Insertion Sort) in una struttura dati. Inizialmente, la sottolista ordinata contiene un solo elemento, ovvero 4. Dopo l'inserimento di A[1], ovvero 3, la dimensione della sottolista ordinata aumenta a 2 e l'algoritmo continua questo schema finchรฉ ogni elemento non รจ stato inserito.

Con il flusso concettuale in atto, le sezioni seguenti mostrano implementazioni concrete in C++, C, e Python in modo da poter confrontare le strutture dei cicli tra diversi linguaggi di programmazione.

C++ Programma per l'ordinamento per inserimento

Migliori C++ L'implementazione seguente utilizza due cicli annidati: il ciclo esterno seleziona il successivo elemento non ordinato, mentre il ciclo interno lo sposta a sinistra finchรฉ non viene trovata la posizione corretta.

#include <iostream>
using namespace std;

int main(){
    //unsorted list
    int unsorted[] = {9,8,7,6,5,4,3,3,2,1};

    //size of list
    int size_unsorted = sizeof(unsorted) / sizeof(unsorted[0]);

    //printing unsorted list
    cout << "\nUnsorted: ";
    for(int i = 0 ; i < size_unsorted ; i++){
        cout << unsorted[i] << " ";
    }

    int current_element,temp;

    for(int i = 1; i < size_unsorted; i++){
        current_element = unsorted[i];
        for(int j = i-1; j >= 0 && unsorted[j] > current_element; j--){
            //swapping if current element is lesser
            temp = unsorted[j+1];
            unsorted[j+1] = unsorted[j];
            unsorted[j] = temp;
        }
    }

    //printing sorted list
    cout << "\nSorted: ";
    for(int i = 0 ; i < size_unsorted ; i++){
        cout << unsorted[i] << " ";
    }

    return 0;
}

Produzione:

Unsorted: 9 8 7 6 5 4 3 3 2 1
Sorted: 1 2 3 3 4 5 6 7 8 9

C Code per l'ordinamento per inserimento

La stessa logica si traduce direttamente in C. Lo standard printf le chiamate sostituiscono l'output del flusso, ma lo schema di scambio all'interno del ciclo interno รจ identico a quello C++ versione.

#include <stdio.h>
int main() {
    //unsorted list
    int unsorted[] = {9,8,7,6,5,4,3,3,2,1};

    //size of list
    int size_unsorted = sizeof(unsorted) / sizeof(unsorted[0]);

    //printing unsorted list
    printf("\nUnsorted: ");
    for(int i = 0 ; i < size_unsorted ; i++){
        printf("%d ", unsorted[i]);
    }

    int current_element, temp;

    for(int i = 1; i < size_unsorted; i++){
        current_element = unsorted[i];
        for(int j = i-1; j >= 0 && unsorted[j] > current_element; j--){
            //swapping if current element is lesser
            temp = unsorted[j+1];
            unsorted[j+1] = unsorted[j];
            unsorted[j] = temp;
        }
    }

    //printing sorted list
    printf("\nSorted: ");
    for(int i = 0 ; i < size_unsorted ; i++){
        printf("%d ", unsorted[i]);
    }

    return 0;
}

Produzione:

Output:
Unsorted: 9 8 7 6 5 4 3 3 2 1
Sorted: 1 2 3 3 4 5 6 7 8 9

Python Programma per l'ordinamento per inserimento

Python supporta lo scambio di tupleping in un'unica espressione, quindi il ciclo interno รจ piรน compatto del suo C e C++ controparti pur preservando lo stesso comportamento algoritmico.

#unsorted list
unsorted = [9,8,7,6,5,4,3,3,2,1]

#size of list
size_unsorted = len(unsorted)

#printing unsorted list
print("\nUnsorted: ", end="")
for i in range(size_unsorted):
    print(unsorted[i], end=" ")

for i in range(1, size_unsorted):
    current_element = unsorted[i]
    j = i - 1
    while j >= 0 and unsorted[j] > current_element:
        #swapping if current element is lesser
        unsorted[j+1], unsorted[j] = unsorted[j], unsorted[j+1]
        j -= 1

#printing sorted list
print("\nSorted: ", end="")
for i in range(size_unsorted):
    print(unsorted[i], end=" ")

Produzione:

Unsorted: 9 8 7 6 5 4 3 3 2 1
Sorted: 1 2 3 3 4 5 6 7 8 9

Proprietร  dell'ordinamento di inserimento

Ecco alcune importanti proprietร  dell'algoritmo di ordinamento per inserimento che ti aiuteranno a decidere quando รจ lo strumento giusto per te:

  • In linea: L'ordinamento per inserimento puรฒ ordinare gli elementi man mano che li riceve. Se abbiamo giร  ordinato un elenco di elementi e ne aggiungiamo altri, non รจ necessario eseguire nuovamente l'intera procedura di ordinamento. Invece, iteriamo solo sugli elementi appena aggiunti.
  • A posto: La complessitร  spaziale dell'algoritmo di ordinamento per inserimento รจ costante e non richiede spazio aggiuntivo. Questo algoritmo ordina gli elementi sul posto.
  • Stabile: Nell'algoritmo di ordinamento per inserimento, gli elementi non vengono scambiati se i loro valori sono uguali. Ad esempio, se due elementi, x e y, hanno lo stesso valore e x appare prima di y nell'elenco non ordinato, anche nell'elenco ordinato x apparirร  prima di y. Questo rende l'algoritmo di ordinamento per inserimento stabile.
  • Adattivo: A algoritmo di ordinamento Un algoritmo di ordinamento รจ adattivo se impiega meno tempo quando gli elementi di input, o un sottoinsieme di essi, sono giร  ordinati. Come discusso in precedenza, il tempo di esecuzione migliore dell'Insertion Sort รจ O(N), mentre il peggiore รจ O(N^2). L'Insertion Sort รจ uno degli algoritmi di ordinamento adattivo.

Complessitร  dell'ordinamento per inserimento

La discussione sulla complessitร  che segue copre sia l'utilizzo della memoria che il tempo di esecuzione, in modo da poter posizionare l'Insertion Sort rispetto ad alternative come Bubble Ordina and Ordinamento rapido.

Complessitร  spaziale

L'algoritmo di ordinamento per inserimento non richiede spazio aggiuntivo per ordinare gli elementi. La complessitร  spaziale รจ costante, ovvero O(1), poichรฉ vengono utilizzate solo poche variabili temporanee indipendentemente dalla dimensione dell'input.

Complessitร  temporale

Poichรฉ l'algoritmo di ordinamento per inserimento itera un elemento alla volta, richiede N-1 passaggi per ordinare N elementi. Per ogni passaggio, potrebbe non effettuare alcuno scambio se gli elementi sono giร  ordinati, oppure potrebbe richiederne molti se gli elementi sono disposti in ordine decrescente.

  • Per il passaggio 1, gli scambi minimi richiesti sono zero e gli scambi massimi richiesti sono 1.
  • Per il passaggio 2, gli scambi minimi richiesti sono zero e gli scambi massimi richiesti sono 2.
  • Per il passaggio N, lo scambio minimo richiesto รจ zero e gli scambi massimi richiesti sono N.
  • Lo scambio minimo รจ zero, quindi la migliore complessitร  temporale รจ O(N) per l'iterazione di N passaggi.
  • Il numero massimo totale di scambi รจ (1+2+3+4+โ€ฆ+N), ovvero N(N+1)/2, quindi la complessitร  temporale peggiore รจ O(N^2).

Ecco la complessitร  temporale piรน importante dell'algoritmo di ordinamento per inserimento:

  • Complessitร  del caso peggiore: O(n^2): Ordinare un array in ordine decrescente quando รจ richiesto un ordine crescente รจ lo scenario peggiore.
  • migliore Complessitร  del caso: O(n): Il caso migliore si verifica quando l'array รจ giร  ordinato; il ciclo esterno viene eseguito n volte, mentre il ciclo interno non viene eseguito affatto. Ci sono solo n confronti, quindi la complessitร  รจ lineare.
  • Complessitร  media del caso: O(n^2): Ciรฒ si verifica quando gli elementi dell'array si presentano in un ordine disordinato che non รจ nรฉ crescente nรฉ decrescente.

DOMANDE FREQUENTI

Scegli l'algoritmo Insertion Sort per array di piccole dimensioni, dati quasi ordinati o inserimenti in streaming in cui i nuovi elementi arrivano dopo un ordinamento iniziale. Il suo basso overhead costante e il comportamento adattivo spesso superano algoritmi piรน complessi in questi carichi di lavoro.

Sรฌ. L'algoritmo Insertion Sort รจ stabile perchรฉ non scambia mai i valori uguali, preservandone l'ordine originale. รˆ inoltre in-place perchรฉ ordina utilizzando solo l'array di input piรน un piccolo numero fisso di variabili temporanee, fornendo uno spazio ausiliario O(1).

Il caso migliore รจ O(n) quando l'input รจ giร  ordinato perchรฉ il ciclo interno non viene mai eseguito. I casi peggiore e medio sono entrambi O(n^2) quando l'array รจ ordinato in modo inverso o disordinato, a causa dello spostamento ripetuto degli elementi verso l'inizio dell'array.

Gli assistenti IA generano animazioni e tabelle passo passo che contrassegnano l'elemento corrente, la regione ordinata e il puntatore di confronto per ogni passaggio. Questa visualizzazione aiuta gli studenti trace scambia, individua gli errori di un'unitร  e conferma che il prefisso ordinato cresca di un elemento ad ogni iterazione esterna.

Sรฌ. I selettori basati sull'IA analizzano le dimensioni, la distribuzione e il preordinamento degli array, quindi instradano gli input piccoli o quasi ordinati all'Insertion Sort, mentre gli input casuali piรน grandi vengono instradati al Quick Sort o al Merge Sort. Algoritmi ibridi come Timsort applicano giร  questa idea all'interno delle loro partizioni interne.

L'algoritmo Insertion Sort costruisce la regione ordinata inserendo ogni nuovo elemento nella posizione corretta, mentre il Selection Sort trova ripetutamente il minimo della regione non ordinata e lo aggiunge. Insertion Sort รจ adattivo e stabile; il Selection Sort standard non รจ adattivo e non รจ intrinsecamente stabile.

Riassumi questo post con: