Sono molto curioso, perché la stabilità è o non è importante negli algoritmi di ordinamento?
IBM (Insertion, Bubble, Merge)
Sono molto curioso, perché la stabilità è o non è importante negli algoritmi di ordinamento?
IBM (Insertion, Bubble, Merge)
Risposte:
Si dice che un algoritmo di ordinamento è stabile se due oggetti con chiavi uguali compaiono nello stesso ordine nell'output ordinato come appaiono nell'array di input da ordinare. Alcuni algoritmi di ordinamento sono stabili per natura come Inserimento ordinamento, Merge Sort, Bubble Sort, ecc. E alcuni algoritmi di ordinamento non lo sono, come Heap Sort, Quick Sort, ecc.
Background : un algoritmo di ordinamento "stabile" mantiene gli articoli con la stessa chiave di ordinamento in ordine. Supponiamo di avere un elenco di parole di 5 lettere:
peach
straw
apple
spork
Se ordiniamo l'elenco solo per la prima lettera di ogni parola, allora un ordinamento stabile produrrebbe:
apple
peach
straw
spork
In un algoritmo di ordinamento instabile , straw
o spork
possono essere scambiati, ma in uno stabile, rimangono nelle stesse posizioni relative (cioè, poiché straw
appare prima spork
nell'input, appare anche prima spork
nell'output).
Potremmo ordinare l'elenco di parole usando questo algoritmo: ordinamento stabile per colonna 5, quindi 4, quindi 3, quindi 2, quindi 1. Alla fine, verrà ordinato correttamente. Convinciti di quello. (a proposito, quell'algoritmo si chiama radix sort)
Ora per rispondere alla tua domanda, supponiamo di avere un elenco di nomi e cognomi. Ci viene chiesto di ordinare "per cognome, poi per primo". Potremmo prima ordinare (stabile o instabile) per nome, quindi ordinare stabile per cognome. Dopo questi tipi, l'elenco viene ordinato principalmente in base al cognome. Tuttavia, dove i cognomi sono gli stessi, i nomi vengono ordinati.
Non è possibile impilare tipi instabili allo stesso modo.
straw
e spork
confrontare uguale. L'ordinamento stabile manterrà l'ordine di input, mentre l'ordinamento instabile non garantisce tale garanzia. "Corretto" dipende dall'applicazione. La funzione di ordinamento nella maggior parte dei linguaggi di programmazione consente all'utente di fornire una funzione di ordinazione personalizzata. Se la funzione dell'utente considera diversi articoli uguali (ad es. Stesso nome, cognome diverso), aiuta a sapere se l'ordine originale verrà conservato. Vedi le funzioni di ordinamento degli array di OCaml per un esempio reale.
Un algoritmo di ordinamento stabile è quello che ordina gli elementi identici nel loro stesso ordine come appaiono nell'input, mentre l'ordinamento instabile potrebbe non soddisfare il caso. - Ringrazio il mio docente di algoritmi Didem Gozupek per aver fornito informazioni sugli algoritmi .
Algoritmi di ordinamento stabili:
Algoritmi di ordinamento instabili:
Stabilità dell'ordinamento significa che i record con la stessa chiave mantengono il loro ordine relativo prima e dopo l'ordinamento.
Quindi la stabilità conta se, e solo se, il problema che stai risolvendo richiede il mantenimento di quell'ordine relativo.
Se non hai bisogno di stabilità, puoi utilizzare un algoritmo veloce e con memoria da una libreria, come heapsort o quicksort, e dimenticartene.
Se hai bisogno di stabilità, è più complicato. Gli algoritmi stabili hanno un utilizzo maggiore della CPU e / o della memoria big-O rispetto agli algoritmi instabili. Quindi, quando si dispone di un set di dati di grandi dimensioni, è necessario scegliere tra battere la CPU o la memoria. Se sei limitato su CPU e memoria, hai un problema. Un buon algoritmo stabile di compromesso è un ordinamento ad albero binario; l' articolo di Wikipedia ha un'implementazione C ++ pateticamente semplice basata sull'STL.
È possibile trasformare un algoritmo instabile in uno stabile aggiungendo il numero del record originale come chiave dell'ultimo posto per ciascun record.
Dipende da cosa fai.
Immagina di avere alcuni record di persone con un campo nome e cognome. Innanzitutto ordina l'elenco per nome. Se poi si ordina l'elenco con un algoritmo stabile per cognome, si avrà un elenco ordinato per nome E cognome.
Ci sono alcuni motivi per cui la stabilità può essere importante. Uno è che, se non è necessario scambiare due record scambiandoli, è possibile causare un aggiornamento della memoria, una pagina viene contrassegnata come sporca e deve essere riscritta su disco (o un altro supporto lento).
Si dice che un algoritmo di ordinamento è stabile se due oggetti con chiavi uguali compaiono nello stesso ordine nell'output ordinato come appaiono nell'array di input non ordinato. Alcuni algoritmi di ordinamento sono stabili per natura come Inserimento ordinamento, Merge Sort, Bubble Sort, ecc. E alcuni algoritmi di ordinamento non lo sono, come Heap Sort, Quick Sort, ecc.
Tuttavia, qualsiasi dato algoritmo di ordinamento che non è stabile può essere modificato per essere stabile. Ci possono essere modi specifici di ordinamento per renderlo stabile, ma in generale, qualsiasi algoritmo di ordinamento basato sul confronto che non è stabile per natura può essere modificato per essere stabile cambiando l'operazione di confronto dei tasti in modo che il confronto di due tasti consideri la posizione come un fattore per oggetti con chiavi uguali.
Riferimenti: http://www.math.uic.edu/~leon/cs-mcs401-s08/handouts/stability.pdf http://en.wikipedia.org/wiki/Sorting_algorithm#Stability
So che ci sono molte risposte per questo, ma per me questa risposta , di Robert Harvey , l'ha sintetizzata molto più chiaramente:
Un ordinamento stabile è uno che preserva l'ordine originale del set di input, in cui l'algoritmo [instabile] non distingue tra due o più elementi.
Se supponi che ciò che stai ordinando siano solo numeri e solo i loro valori li identificano / li distinguono (ad es. Elementi con lo stesso valore sono identici), allora il problema di stabilità dell'ordinamento è insignificante.
Tuttavia, gli oggetti con la stessa priorità nell'ordinamento possono essere distinti e talvolta il loro ordine relativo è un'informazione significativa. In questo caso, l'ordinamento instabile genera problemi.
Ad esempio, hai un elenco di dati che contiene il costo del tempo [T] di tutti i giocatori per pulire un labirinto con Livello [L] in una partita. Supponiamo di dover classificare i giocatori in base alla velocità con cui puliscono il labirinto. Tuttavia, si applica una regola aggiuntiva: i giocatori che puliscono il labirinto con un livello superiore hanno sempre un rango più alto, indipendentemente da quanto tempo sia il costo.
Naturalmente potresti provare a mappare il valore accoppiato [T, L] su un numero reale [R] con un algoritmo che segue le regole e quindi classificare tutti i giocatori con valore [R].
Tuttavia, se è possibile un ordinamento stabile, puoi semplicemente ordinare l'intero elenco per [T] (prima i giocatori più veloci) e poi per [L]. In questo caso, l'ordine relativo dei giocatori (in base al costo del tempo) non verrà modificato dopo averli raggruppati per livello di labirinto che hanno pulito.
PS: ovviamente l'approccio per ordinare due volte non è la soluzione migliore al problema particolare, ma per spiegare la questione del poster dovrebbe essere sufficiente.
L'ordinamento stabile restituirà sempre la stessa soluzione (permutazione) sullo stesso input.
Ad esempio [2,1,2] verrà ordinato usando l'ordinamento stabile come permutazione [2,1,3] (prima l'indice 2, quindi l'indice 1 quindi l'indice 3 nell'output ordinato) Ciò significa che l'output viene sempre mischiato allo stesso modo. Un'altra permutazione non stabile, ma ancora corretta è [2,3,1].
L'ordinamento rapido non è un ordinamento stabile e le differenze di permutazione tra gli stessi elementi dipendono dall'algoritmo per la selezione del perno. Alcune implementazioni prendono a caso e ciò può rendere veloce l'ordinamento producendo permutazioni diverse sullo stesso input usando lo stesso algoritmo.
L'algoritmo di ordinamento stabile è deterministico necessario.
sort([(5,3),(1,5),(3,3),(1,3)], x) => [(1,5),(1,3),(3,3),(5,3)]
. Posso fare un ordinamento deterministico che produce sempre (deterministicamente): [(1,3),(1,5),(3,3),(5,3)]
ma questo non è un ordinamento stabile.
Alcuni altri esempi del motivo per volere tipi stabili. I database sono un esempio comune. Prendiamo il caso di una base di dati di transazione che include cognome | nome, data | ora di acquisto, numero articolo, prezzo. Supponiamo che il database sia normalmente ordinato per data | ora. Quindi viene eseguita una query per creare una copia ordinata della base di dati in base al cognome |, poiché un ordinamento stabile preserva l'ordine originale, anche se il confronto delle richieste comporta solo il cognome |, le transazioni per ciascun | cognome essere nell'ordine di data | time.
Un esempio simile è Excel classico, che ha limitato l'ordinamento a 3 colonne alla volta. Per ordinare 6 colonne, viene eseguito un ordinamento con le 3 colonne meno significative, seguito da un ordinamento con le 3 colonne più significative.
Un classico esempio di ordinamento radix stabile è uno smistatore di carte, utilizzato per ordinare in base a un campo di 10 colonne numeriche di base. Le carte sono ordinate dalla cifra meno significativa alla cifra più significativa. Ad ogni passaggio, un mazzo di carte viene letto e diviso in 10 diversi contenitori in base alla cifra in quella colonna. Quindi i 10 scomparti di carte vengono rimessi nell'hopper di input in ordine (prima le carte "0", le ultime "9"). Quindi un altro passaggio viene eseguito dalla colonna successiva, fino a quando tutte le colonne non vengono ordinate. I selezionatori di carte effettivi hanno più di 10 scomparti poiché ci sono 12 zone su una carta, una colonna può essere vuota e c'è un cestino erroneamente letto. Per ordinare le lettere, sono necessari 2 passaggi per colonna, 1 ° passaggio per cifra, 2 ° passaggio per la zona 12 11.
Più tardi (1937) c'erano macchine per la raccolta (fusione) di carte che potevano unire due mazzi di carte confrontando i campi. L'input consisteva in due mazzi di carte già ordinati, un mazzo principale e un mazzo di aggiornamento. Il raccoglitore ha unito i due deck in un nuovo contenitore di materiali e un contenitore di archiviazione, che è stato facoltativamente utilizzato per i duplicati principali in modo che il nuovo contenitore principale avesse solo schede di aggiornamento in caso di duplicati. Questa è stata probabilmente la base dell'idea alla base della fusione originale (dal basso verso l'alto).