Quindi, in sostanza, vuoi sapere se esiste un algoritmo di ordinamento che non si degraderebbe dal suo caso medio se avesse una funzione di confronto simile a:
int Compare(object a, object b) { return Random.Next(-1,1); }
... dove Random.Next () è un metodo che produrrà un numero intero generato casualmente tra un limite inferiore e superiore inclusi.
La risposta è in realtà che la maggior parte degli algoritmi di ordinamento di base funzionerà secondo il loro caso medio, perché obbediscono ad almeno una delle due seguenti condizioni:
- Un confronto tra due elementi unici non viene mai effettuato due volte nell'ordinamento e / o
- In ogni iterazione dell'ordinamento, viene determinata la posizione corretta di almeno un elemento e quindi l'elemento non viene mai più confrontato.
Ad esempio, SelectionSort scorre l'elenco secondario di elementi non ordinati, trova l'elemento "minimo" e / o "maggiore" (confrontando ciascuno con il massimo finora), lo posiziona nella posizione corretta e si ripete. Di conseguenza, anche con un comparatore non deterministico, alla fine di ogni iterazione l'algoritmo avrà trovato un valore che ritiene minimo o maggiore, lo scambia con l'elemento nella posizione che sta cercando di determinare e non considera mai quell'elemento di nuovo, quindi obbedisce alla Condizione 2. Tuttavia, A e B possono essere confrontati più volte durante questo processo (come esempio più estremo, considera diversi passaggi di SelectionSort su un array che è ordinato in ordine inverso), quindi viola la Condizione 1 .
MergeSort obbedisce alla Condizione 1 ma non a 2; man mano che i sotto-array vengono uniti, gli elementi nello stesso sotto-array (sul lato sinistro o destro) non vengono confrontati tra loro perché è già stato stabilito che gli elementi su quel lato dell'array sono in ordine tra loro; l'algoritmo confronta solo l'elemento meno immerso di ciascun subarray con l'altro per determinare quale è minore e dovrebbe andare successivamente nell'elenco unito. Ciò significa che due oggetti unici A e B verranno confrontati tra loro al massimo una volta, ma l'indice "finale" di un determinato elemento nell'intera raccolta non è noto fino a quando l'algoritmo non è completo.
InsertionSort obbedisce solo alla Condizione 1, anche se la sua strategia e complessità complessive assomigliano più a SelectionSort. Ogni elemento non ordinato viene confrontato con elementi ordinati, il più grande per primo, fino a quando non ne viene trovato uno inferiore all'elemento in esame. l'elemento viene inserito in quel punto e quindi viene considerato l'elemento successivo. Il risultato è che l'ordine relativo di qualsiasi A e B è determinato da un confronto, e ulteriori confronti tra tale A e B non vengono mai eseguiti, ma la posizione finale di qualsiasi elemento non può essere conosciuta fino a quando non vengono considerati tutti gli elementi.
QuickSort obbedisce ad entrambiCondizioni. Ad ogni livello, un perno viene scelto e disposto in modo tale che il lato "sinistro" contenga elementi inferiori al perno e il lato "destro" contenga elementi maggiori del perno. Il risultato di quel livello è QuickSort (a sinistra) + pivot + QuickSort (a destra) che sostanzialmente significa che la posizione dell'elemento pivot è nota (un indice maggiore della lunghezza del lato sinistro), il pivot non viene mai confrontato con nessun altro elemento dopo che è stato scelto come perno (potrebbe essere stato confrontato con elementi pivot precedenti, ma quegli elementi sono anche noti e non sono inclusi in alcun subarrays), E qualsiasi A e B che finiscono su lati opposti del perno non sono mai rispetto. Nella maggior parte delle implementazioni di QuickSort puro, il caso base è un elemento, a quel punto il suo indice corrente è il suo indice finale e non vengono effettuati ulteriori confronti.
( 2 / 3 )N- 1). All'aumentare del valore assoluto massimo del risultato del comparatore, la probabilità che uno qualsiasi di questi confronti ritorni negativo o zero diminuisce verso 0,5, rendendo la possibilità di terminare l'algoritmo molto meno probabile (la possibilità di 99 gettoni lancia tutte le teste di atterraggio , che è sostanzialmente ciò a cui si riduce, è 1 in 1,2 * 10 30 )
EDIT A LATER LONG TIME: Ci sono alcuni "tipi" progettati specificamente come esempi di cosa non fare che incorporano un comparatore casuale; forse il più famoso è BogoSort. "Dato un elenco, se l'elenco non è in ordine, mescola l'elenco e ricontrolla". Teoricamente alla fine colpirà la giusta permutazione di valori, proprio come il "BubbleSort non ottimizzato" sopra, ma il caso medio è tempo fattoriale (N! / 2), e a causa del problema del compleanno (dopo sufficienti permutazioni casuali tu diventare più probabilità di incontrare permutazioni duplicate rispetto a quelle uniche) c'è una possibilità diversa da zero che l'algoritmo che non si completa ufficialmente non è limitato nel tempo.