C++: differenze tra le versioni

Contenuto cancellato Contenuto aggiunto
m Annullata la modifica 53634 di Wiliam Polidori (discussione)
Riga 335:
==La gestione delle eccezioni==
==Metodi di ricerca e ordinamento==
Bubble sort
Da Wikipedia, l'enciclopedia libera.
Vai a: Navigazione, cerca
Bubble sort
Bubble sort in esecuzione su una lista di numeri
Classe Algoritmo di ordinamento
Struttura dati Array
Caso pessimo temporalmente O(n2)
Caso ottimo temporalmente O(n)
Caso medio temporalmente O(n2)
Caso pessimo spazialmente O(n) totale, O(1) ausiliario
Ottimale No
Completo {{{complete}}}
Questo box: vedi • disc. • mod.
Il bubble sort o bubblesort (letteralmente: ordinamento a bolle) è un semplice algoritmo di ordinamento per ordinare array.
 
Il nome dell'algoritmo è dovuto al fatto che, durante l'applicazione del procedimento, i valori vengono spostati all'interno dell'array con una dinamica che ricorda il movimento delle bollicine in un bicchiere di champagne. In particolare, alcuni elementi attraversano l'array velocemente (come bollicine che emergono dal fondo del bicchiere), altri più lentamente.
 
Come tutti gli algoritmi di ordinamento, può essere usato per ordinare dati di un qualsiasi tipo su cui sia definita una relazione d'ordine.
 
Non è un algoritmo efficiente: ha una complessità computazionale dell'ordine di O(n2) confronti, con n numero degli elementi da ordinare; si usa solamente a scopo didattico in virtù della sua semplicità, e per introdurre i futuri programmatori al ragionamento algoritmico e alle misure di complessità.
 
Dell'algoritmo esistono numerose varianti, per esempio lo shakersort.
 
Indice [mostra]
1 Spiegazione astratta
1.1 Analisi dell'algoritmo
1.2 Varianti e ottimizzazioni
2 Pseudocodice
3 Altri progetti
4 Collegamenti esterni
 
Spiegazione astratta [modifica]
Il bubblesort è un algoritmo iterativo, ossia basato sulla ripetizione di un procedimento fondamentale. La singola iterazione dell'algoritmo prevede che gli elementi dell'array siano confrontati a due a due, procedendo in un verso stabilito (che si scandisca l'array a partire dall'inizio in avanti, o a partire dal fondo all'indietro, è irrilevante; nel seguito ipotizzeremo che lo si scandisca partendo dall'inizio).
 
Per esempio, saranno confrontati il primo e il secondo elemento, poi il secondo e il terzo, poi il terzo e il quarto, e così via fino al confronto fra penultimo e ultimo elemento. Per ogni confronto, se i due elementi confrontati non sono ordinati, essi vengono scambiati. Durante ogni iterazione, almeno un valore viene spostato rapidamente fino a raggiungere la sua collocazione definitiva; in particolare, alla prima iterazione il numero più grande raggiunge l'ultima posizione dell'array.
 
Il motivo è semplice, e si può illustrare con un esempio. Supponiamo che l'array sia inizialmente disposto come segue:
 
15 6 4 10 11 2
Inizialmente 15 viene confrontato con 6, ed essendo 15>6, i due numeri vengono scambiati:
 
6 15 4 10 11 2
A questo punto il 15 viene confrontato col 4, e nuovamente scambiato:
 
6 4 15 10 11 2
Non è difficile osservare che, essendo 15 il numero massimo, ogni successivo confronto porterà a uno scambio e a un nuovo spostamento di 15, che terminerà nell'ultima cella dell'array. Per motivi analoghi, alla seconda iterazione è garantito che il secondo numero più grande raggiungerà la sua collocazione definitiva nella penultima cella dell'array, e via dicendo. Ne conseguono due considerazioni:
 
se i numeri sono in tutto N, dopo N-1 iterazioni si avrà la garanzia che l'array sia ordinato;
alla iterazione i-esima, le ultime i-1 celle dell'array ospitano i loro valori definitivi, per cui la sequenza di confronti può essere terminata col confronto dei valori alle posizioni N-1-i e N-i.
Ovviamente, a ogni iterazione può accadere che più numeri vengano spostati; per cui, oltre a portare il numero più grande in fondo all'array, ogni singola iterazione può contribuire anche a un riordinamento parziale degli altri valori. Anche per questo motivo, può accadere (normalmente accade) che l'array risulti ordinato prima che si sia raggiunta la N-1esima iterazione. Su questa osservazione sono basate alcune ottimizzazioni dell'algoritmo.
 
Analisi dell'algoritmo [modifica]
Il bubble sort effettua all'incirca confronti ed scambi sia in media che nel caso peggiore. Il tempo di esecuzione dell'algoritmo è Θ(n2).
 
Varianti e ottimizzazioni [modifica]
Esistono numerose varianti del bubblesort, molte delle quali possono essere definite ottimizzazioni nel senso che mirano a ottenere lo stesso risultato finale (l'ordinamento dell'array) eseguendo, in media, meno operazioni.
 
Un insieme di ottimizzazioni sono basate sull'osservazione che se, in una data iterazione, non avviene alcuno scambio, allora l'array è necessariamente ordinato e l'algoritmo può essere terminato anticipatamente (ovvero senza giungere alla N-1esima iterazione). Una tecnica di ottimizzazione può dunque essere applicata usando una variabile booleana (o equivalente) usata come "flag" che indica se l'iterazione corrente ha prodotto uno scambio. La variabile viene reimpostata a false all'inizio di ogni iterazione, e impostata a true solo nel caso in cui si proceda a uno scambio. Se al termine di una iterazione completa il valore della variabile flag è false, l'intero algoritmo viene terminato. Questa tecnica produce una riduzione del tempo medio di esecuzione dell'algoritmo, pur con un certo overhead costante (assegnamento e confronto della variabile flag).
 
Una seconda linea di ottimizzazione (che può essere combinata con la prima) è basata sull'osservazione che (sempre assumendo una scansione dell'array, per esempio, in avanti, e ordinamento crescente) se una data iterazione non sposta nessun elemento di posizione maggiore di un dato valore i, allora si può facilmente dimostrare che nessuna iterazione successiva eseguirà alcuno scambio in posizioni successive a tale valore i. L'algoritmo può dunque essere ottimizzato memorizzando l'indice a cui avviene l'ultimo scambio durante una iterazione, e limitando le iterazioni successive alla scansione dell'array solo fino a tale posizione. Anche questa tecnica evidentemente introduce un piccolo overhead (gestione della variabile aggiuntiva che indica la posizione di ultima modifica).
 
Un'altra variante già menzionata (lo shakersort) consente di ridurre la probabilità che si verifichi la situazione di caso peggiore (in cui tutte le ottimizzazioni precedentemente citate falliscono e quindi contribuiscono solo negativamente con i relativi overhead); vedi la voce relativa.
 
Pseudocodice [modifica]
Segue lo pseudocodice per l'algoritmo.
 
BubbleSort(array[], elemN)
alto ← elemN
while (alto > 0) do
for i ← 0 to alto - 1 do
if (array[i] > array[i + 1]) then //scambiare il '>' con '<' per ottenere
tmp ← array[i] // un ordinamento decrescente
array[i] ← array[i + 1]
array[i+1] ← tmp
alto ← alto - 1
 
==Altri Progetti==