Peggiore caso in atto ordinamento stabile?


35

Ho problemi a trovare buone risorse che danno il peggior caso in atto algoritmo di ordinamento stabile . Qualcuno sa di buone risorse?O(nlnn)

Solo un promemoria, sul posto significa che utilizza l'array passato e che l'algoritmo di ordinamento è autorizzato a utilizzare solo spazio aggiuntivo costante. Stabile significa che gli elementi con la stessa chiave appaiono nello stesso ordine nell'array ordinato come nell'originale.

Ad esempio, l'ordinamento unificato ingenuo è il caso peggiore e stabile ma utilizza spazio aggiuntivo. Quicksort standard può essere reso stabile, è presente ma nella peggiore delle ipotesi . Heapsort è a posto, nel peggiore dei casi ma non è stabile. Wikipedia ha un bel grafico di quali algoritmi di ordinamento hanno quali inconvenienti. Si noti che non esiste un algoritmo di ordinamento che elenca che abbia tutte e tre le condizioni di stabilità, nel caso peggiore e di essere in atto.O ( n ) O ( n 2 ) O ( n ln n )O(nlnn)O(n)O(n2)O(nlnn)O(nlnn)

Ho trovato un documento intitolato "Pratica sul posto sul posto" di Katajainen, Pasanen e Teuhola, che afferma di avere il caso peggiore in atto una variante stabile del mergesort. Se capisco correttamente i loro risultati, usano (bottom-up?) La fusione in modo ricorsivo sul primo dell'array e sul secondo dell'array e usano il secondo come spazio scratch per fare l'unione. Lo sto ancora leggendo, quindi vengono apprezzate ulteriori informazioni sull'interpretazione corretta dei loro risultati.1O(nlnn) 114 11214

Sarei anche molto interessato al peggiore dei casi sul posto di quicksort stabile. Da quello che ho capito, la modifica di quicksort in caso peggiore richiede la selezione di un perno adatto che distruggerebbe la stabilità che altrimenti godrebbe normalmente.O ( n ln n )O(nlnn)O(nlnn)

Questo è puramente di interesse teorico e non ho alcuna applicazione pratica. Vorrei solo sapere l'algoritmo che ha tutte e tre queste caratteristiche.


C'è una domanda simile su SO qui con una risposta che fornisce il riferimento che ho fornito nella domanda. Credo che questa non sia una domanda duplicata in quanto sto chiedendo ulteriori chiarimenti, più letteratura e, con un po 'di fortuna, una descrizione dell'algoritmo.
user834

1
Vedi questa domanda su math.stackexchange.com.
Tsuyoshi Ito,

Perché un modo diverso di selezionare un perno in QuickSort ne distruggerebbe la stabilità?
svick

@svick, l'unico modo in cui so come peggiorare QuickSort è scegliere il perno in modo più intelligente che casuale. Il modo in cui ho imparato a farlo è stato usando l'algoritmo di selezione, che utilizza l'algoritmo mediano delle mediane, che distrugge la stabilità. Se ho perso qualcosa, per favore fatemi sapere. O(nlnn)
user834

@TsuyoshiIto, prendi in considerazione di fare di questo una risposta. Inoltre, se potessi fornire un breve schizzo dell'algoritmo, penso che sarebbe davvero utile.
user834,

Risposte:


6

Esistono diversi algoritmi di cui sopra e praticamente tutti sono stati inventati negli ultimi 30 anni.

Probabilmente la più bella è la classe di algoritmi chiamata Block sort , inclusa la versione (chiamata WikiSort) di Kim e Kutzner nel 2008. Non è solo stabile e completamente sul posto (O (1) overhead di memoria nel modello transdicotomo), ma è anche adattivo e quindi richiederà meno passaggi per ordinare gli elenchi quasi ordinati, convergendo a confronti O (n) nel caso di un elenco già ordinato. Puoi trovare un'implementazione in C, C ++ e Java qui: https://github.com/BonzaiThePenguin/WikiSort

Altrettanto interessante è l'algoritmo GrailSort (anche un tipo di blocco) di Huang e Langston (1989-1992), che supera di fatto WikiSort su diversi tipi di casi di test. Un'implementazione C ++ è disponibile qui: https://github.com/Mrrl/GrailSort


8

È possibile scrivere un mergesort sul posto e stabile. Vedi questo per i dettagli. Nelle parole dell'autore:

Un bellissimo algoritmo: unisci. Provalo su array invertiti per capire come funzionano le rotazioni. Ordinamento stabile sul posto più veloce conosciuto. Nessun rischio di esplodere uno stack. Costo: un numero relativamente elevato di mosse. Anche lo stack può essere costoso. Si tratta di un ordinamento di tipo merge con un'unione intelligente in atto che "ruota" gli array secondari. Questo codice viene letteralmente copiato dalla libreria C ++ stl e tradotto in Java.

Non copierò il codice qui, ma puoi trovarlo sul link o controllando il C ++ STL. Per favore fatemi sapere se volete che provi a fornire una descrizione più dettagliata di ciò che sta succedendo qui.


8
O(lnn)O(1)O(lnn)

Knuth si occupa anche di questo in TAoCP.
Raffaello

O(nln2n)

1

Si prega di prendere questo come un lungo commento su alcuni pensieri pratici. Sebbene questa non sia una risposta alla tua domanda, penso che potresti essere interessato a questa discussione su Python:

lg(N!)N-1

[...]

La fusione di piste adiacenti delle lunghezze A e B sul posto è molto difficile . Sono note costruzioni teoriche che possono farlo, ma sono troppo difficili e lente per un uso pratico . Ma se abbiamo una memoria temporanea uguale a min (A, B), è facile.

Fonte: bugs.python.org , autore: Tim Peters

O(nlogn)

Si noti inoltre che Timsort funziona bene su array già ordinati.

Quindi Python fa uso di Timsort (che è Mergesort con alcune modifiche) e mentre ho cercato l'implementazione Java alcuni anni fa, è stato anche Mergesort (penso che ora usino anche Timsort).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.