gl/ripetizioni

Algoritmi di ordinamento: bubble, selection e insertion sort

Bubble, selection e insertion sort spiegati con una traccia passo-passo su 6 numeri: pseudocodice, Python, confronti, scambi, O(n²) ed esercizi svolti.

di Gaetano Livornese

  • #informatica
  • #terza superiore
  • #liceo scientifico
  • #algoritmi di ordinamento
  • #bubble sort
  • #programmazione

Se sei in terza al liceo scientifico, opzione scienze applicate, e a ottobre in informatica avete finito (o state finendo) cicli e array, gli algoritmi di ordinamento sono il passo successivo: di solito arrivano tra ottobre e novembre, e la verifica che li contiene cade fra sei e nove settimane. C’è tempo per capirli davvero, invece di impararli a memoria. Se ti manca la base sugli array, parti da cicli e array; per il costo degli algoritmi in generale c’è la complessità con la notazione O-grande, qui la tocco solo in modo intuitivo.

L’idea in una riga ciascuno

Dobbiamo ordinare un array in modo crescente. Tre strategie, tutte basate su confronti e scambi:

  • Bubble sort: confronta coppie adiacenti e le scambia se sono nell’ordine sbagliato. A ogni passata il valore più grande “sale” in fondo, come una bolla.
  • Selection sort: a ogni passata cerca il minimo della parte non ancora ordinata e lo porta nella prima posizione libera.
  • Insertion sort: tiene ordinata la parte sinistra e inserisce, uno alla volta, l’elemento successivo nel posto giusto, come quando ordini le carte in mano.

Traccia su un array di 6 elementi

Useremo sempre . Le tracce a mano sono ciò che ti chiedono in verifica, quindi leggile con la matita in mano.

Bubble sort

Passata 1 (5 confronti): scambio → ; scambio → ; no; scambio → ; scambio → . Il 6 è al suo posto definitivo.

Passata 2 (4 confronti): no; no; scambio; scambio → .

Passata 3 (3 confronti): no; scambio; scambio → .

Passata 4 (2 confronti): scambio → ; no.

Passata 5 (1 confronto): no. Totale: 15 confronti e 9 scambi.

Selection sort

  • : il minimo di tutto l’array è 1 (posizione 4); scambio con il 5 → .
  • : il minimo di è 2, già al suo posto; niente scambio.
  • : il minimo di è 3; scambio con il 4 → .
  • : il minimo di è 4; scambio con il 6 → .
  • : il minimo di è 5, già al suo posto.

Totale: 15 confronti e 3 scambi (al massimo ).

Insertion sort

Qui si “spostano” elementi verso destra per fare spazio, poi si inserisce la chiave .

  • : il 5 è maggiore, si sposta → (1 spostamento).
  • : il 5 si sposta, il 2 no → (1).
  • : il 5 non è maggiore di 6, resta dov’è (0).
  • : si spostano 6, 5, 4, 2, poi 1 va in testa → (4).
  • : si spostano 6, 5, 4, il 2 no → (3).

Totale: 12 confronti e 9 spostamenti. Il 9 non è un caso: coincide con il numero di scambi del bubble sort, perché entrambi eliminano una per una le inversioni, cioè le coppie in cui un elemento più grande sta prima di uno più piccolo. In sono .

Pseudocodice e Python

Bubble sort, in pseudocodice:

per i da 0 a n-2:
    per j da 0 a n-2-i:
        se a[j] > a[j+1]:
            tmp = a[j]
            a[j] = a[j+1]
            a[j+1] = tmp

In Python lo scambio si può scrivere in una riga, ma capire la versione con tmp serve in tutti gli altri linguaggi:

def bubble_sort(a):
    n = len(a)
    for i in range(n - 1):
        for j in range(n - 1 - i):
            if a[j] > a[j + 1]:
                a[j], a[j + 1] = a[j + 1], a[j]
def selection_sort(a):
    n = len(a)
    for i in range(n - 1):
        m = i
        for j in range(i + 1, n):
            if a[j] < a[m]:
                m = j
        a[i], a[m] = a[m], a[i]
def insertion_sort(a):
    for i in range(1, len(a)):
        k = a[i]
        j = i - 1
        while j >= 0 and a[j] > k:
            a[j + 1] = a[j]
            j -= 1
        a[j + 1] = k

Quando passi un array a una funzione che lo modifica, ricorda come funziona il passaggio dei parametri: ne parlo in valore e riferimento.

Perché sono O(n²) e quale scegliere

In tutti e tre ci sono due cicli annidati. Il ciclo esterno gira circa volte e l’interno, in media, circa : i confronti sono dell’ordine di

Per fa 15, ed è proprio il numero che abbiamo contato. Se raddoppi i confronti diventano circa quattro volte tanti: è il significato intuitivo di .

Quale scegliere:

AlgoritmoConfrontiScambi o spostamentiQuando conviene
bubblemoltiquasi mai; utile per imparare
selection sempreal più quando scrivere è costoso
insertionda a uguali alle inversioniarray piccoli o quasi ordinati

Nel bubble sort puoi aggiungere un controllo: se in una passata non avviene nessuno scambio, l’array è già ordinato e ti fermi. Su un array già ordinato fa solo confronti.

Gli errori che vedo di più

Limiti dei cicli sbagliati. Nel bubble sort l’indice interno arriva a (in Python range(n-1-i)) perché dentro il ciclo si legge a[j+1]: con un limite di troppo si esce dall’array. Allo stesso modo il ciclo esterno non deve arrivare a . Nel selection sort il ciclo interno parte da , non da , altrimenti confronti l’elemento con se stesso.

Scambio senza variabile temporanea. Scrivere a[j] = a[j+1] e subito dopo a[j+1] = a[j] copia lo stesso valore due volte e il valore originale di a[j] è perso.

Confondere selection e bubble. Il selection sort cerca prima il minimo e poi scambia una volta; il bubble scambia durante la scansione.

Dimenticare lo spostamento dell’insertion sort. Se non salvi la chiave prima di spostare gli elementi, la sovrascrivi.

Tre esercizi svolti

1. Caso peggiore del bubble sort

Conta confronti e scambi del bubble sort su .

Passata 1: , , sono tre confronti e tre scambi → . Passata 2: e , due scambi → . Passata 3: , uno scambio → . Totale: confronti e scambi, cioè tutte le 6 coppie sono inversioni. Con l’array già ordinato e il controllo di uscita anticipata, invece, 3 confronti e 0 scambi.

2. Quanto cresce il costo

Quanti confronti servono per ordinare 10, 100 e 1000 elementi con il selection sort? E 2000?

Per 2000: , circa 4 volte i 499 500 di prima: raddoppiando il costo quadruplica. Moltiplicare per 10 moltiplica i confronti per circa 100.

3. Trova l’errore

Questo bubble sort in un linguaggio senza scambio multiplo ha due errori. Quali?

per j da 0 a n-1-i:
    se a[j] > a[j+1]:
        a[j] = a[j+1]
        a[j+1] = a[j]

Primo errore: con fino a , quando si arriva a e si legge a[n], fuori dall’array; il limite corretto è . Secondo errore: lo scambio. Con , la prima assegnazione dà e la seconda lo lascia : il 7 è sparito. Serve tmp = a[j] prima della prima assegnazione e a[j+1] = tmp alla fine.

Metti alla prova

Per allenarti sul ragionamento a tempo puoi usare i simulatori per il liceo. Per informatica non c’è ancora una simulazione dedicata: i quesiti che trovi riguardano matematica e fisica. Un buon modo per prepararti è rifare le tre tracce senza guardare, cambiando l’array. Altre risorse sono nella pagina informatica; se ti serve una mano, faccio ripetizioni 1-a-1 online e puoi partire da una diagnosi gratuita. Vicino a questo argomento c’è anche la ricorsione, che di solito segue gli ordinamenti.

Domande frequenti

Qual è la differenza tra bubble sort e selection sort?

Il bubble sort scambia continuamente coppie adiacenti fuori ordine, quindi può fare molti scambi. Il selection sort cerca il minimo della parte non ordinata e fa al più uno scambio per passata.

Perché questi algoritmi sono O(n²)?

Hanno due cicli annidati: per n elementi i confronti sono circa n(n-1)/2, quindi raddoppiando n i confronti diventano circa quattro volte tanti.

Quale algoritmo di ordinamento conviene scegliere su un array quasi ordinato?

L'insertion sort: se ogni elemento è già vicino alla sua posizione, ogni inserimento richiede pochissimi confronti e il costo si avvicina a quello di una sola scansione.

Come si scambiano due valori in un linguaggio senza assegnazione multipla?

Serve una variabile temporanea: si salva a in tmp, si copia b in a e poi tmp in b. Senza tmp, dopo a = b il vecchio valore di a è perso e i due elementi diventano uguali.

Continua a leggere

Post correlati.

Vuoi applicare quello che hai letto?

Parliamone 30 minuti gratis: guardiamo insieme dove sei bloccato e ti dico onestamente come posso aiutarti.

Oppure scrivimi su WhatsApp.