Ordine rapida in C

Ordine rapida in C

“Quicksort o Quick-Sort è un algoritmo di smistamento. Quick Ord è un algoritmo di divisione e conquista. Lascia che l'elenco dei personaggi sia ordinato da:

Q w e r t y u i o p

L'elenco ordinato è:

E i o p q r t u w y

Questo è una specie di ascesa. In questo articolo, la spiegazione di QuickSort, ordina ascendente, usando l'elenco: "q", "w", "e", "r", "t", "y", "u", "io", " O "," p " e la lingua C."

Ordine rapida in teoria

Dall'elenco, "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", il sorgente sembrerà per un valore centrale, chiamato perno. Nell'elenco ordinato,

"E", "i", "o", "p", "q", "r", "t", "u", "w", "y"

Il perno è "Q" o "R" poiché l'elenco è persino in numero. Se l'elenco fosse dispari in numero, il perno sarebbe stato chiaramente il valore medio. "Q" all'indice 4 è scelto come perno. Ricorda che l'elenco da risolvere è,

Q w e r t y u i o p

e non l'elenco ordinato. Ci sono 10 elementi in questa lista non desiderata.

La prima fase è cercare il perno (valore centrale) nell'elenco non cortioso. La seconda fase è quella di posizionare il perno nella sua legittima posizione nell'elenco non cortioso (in questo caso, indice 4); e mettere tutti gli elementi che sono inferiori al perno a sinistra e tutti gli elementi che sono maggiori del perno a destra. Gli elementi a sinistra del perno non devono necessariamente essere ordinati e gli elementi a destra del perno non devono necessariamente essere ordinati. Questa fase è la fase di divisione o di partizione nell'algoritmo di divisione e conquista. Ci sono tre parti per questa fase: la sotto-list di sinistra, la sotto-list destra e la sotto-list centrale. La sotto-list centrale è costituita da un solo elemento, che è il perno. Per l'elenco di cui sopra, il risultato sarebbe:

E i o p q w r t y u

Poiché il perno è già nella sua posizione finale, l'ultima fase, in teoria, è quello di ordinare la sotto-list di sinistra e ordinare la sotto-list destra. Questo sta conquistando. È una coincidenza che la sotto-list di sinistra, in questo caso, sia già ordinata. La sotto-list giusta, in questo caso, deve ancora essere ordinata. Ordinamento della sotto-list sinistra e destra separatamente, il risultato è:

E i o p q r t u w y

come richiesto.

Ordine rapida in pratica

In pratica, il partizionamento con un po 'di smistamento (scambio) viene eseguito ripetutamente in modo ricorsivo. Cioè, nuovi sotto-listi sempre più piccoli sono sviluppati con i propri pivot. In altre parole, i sotto-listi in tre parti più piccoli vengono sviluppati dall'elenco principale fino a quando l'intero elenco non viene ordinato.

C'è un problema quando si tratta di scegliere il perno. L'intero elenco non preventivo non può essere scansionato elemento per elemento per ottenere il perno giusto. Che richiederà molto tempo. Quindi deve essere fatta un'ipotesi intelligente.

Ricorda che l'elenco da risolvere è:

Q w e r t y u i o p

Lascia che l'ipotesi intelligente sia P, l'elemento più a destra. Successivamente, lascia che tutti gli elementi meno di P, leggendo da sinistra, vadano a sinistra di P e lascia che tutti gli elementi più grandi di P, leggono ancora da sinistra, vadano a destra di P senza smistamento cosciente. Questo da:

E i o p q w r t y u

I primi tre sotto-listi sono:

"E", "i", "o", "p", "q", "w", "r", "t", "y", "u"

P è nella sua posizione legittima (in pratica, potrebbe non essere necessariamente indice 4; qui, è indice 3 in questa fase). Il passo successivo è una chiamata ricorsiva per dividere la sotto-list di sinistra in tre secondari; e il sotto-list destro in tre sotto-list, ognuno con il proprio perno, da un'ipotesi intelligente.

Dividi "e", "i", "o"
Lascia che la sua ipotesi di pivot intelligente sia, o, l'elemento più a destra. Tutti gli elementi che sono inferiori a O devono andare a sinistra e tutti gli elementi che sono maggiori di O devono andare a destra, leggendo per entrambi i casi da sinistra. Questo da:

"E", "i", "o",

senza elemento a destra. If "e", "i" è anche diviso in modo ricorsivo, allora ["e", "i", ] risulterà. E così la prima sotto-list a sinistra ordinata, è:

"E", "i", "o"

Dividi "q", "w", "r", "t", "y", "u"
"Q", "W", "R", "T", "Y", "U" è la prima sotto-list destra. Lascia che sia la sua supposizione di perno intelligente, l'elemento più a destra. Tutti gli elementi che sono meno di quanto tu debba andare a sinistra e tutti gli elementi che sono più grandi di quanto tu debba andare a destra; leggere per entrambi i casi, da sinistra. Questo da:

"Q", "r", "t", "u", “w”, “t”

Partizionando in modo ricorsivo "Q", "R", "T" e “W”, “T” allo stesso modo, la prima sotto-list a destra sarebbe:

"Q", "R", "T", "U", "W", "Y"

E l'elenco ordinato completo sarebbe:

E i o p q r t u w y

Si noti che ogni partizione esegue l'ordinamento in senso lato posizionando valori più bassi non mobili a sinistra e valori più alti non disponibili a destra a destra.

Inoltre, si noti che l'ipotesi intelligente era solo scegliere l'elemento più giusto di un sotto-list. Questa non è la migliore ipotesi intelligente. D'altra parte, la soluzione (per ipotesi intelligente) non è quella di scansionare l'intero elenco fornito! - Vedi sotto per opzioni migliori.

Codice di ordinamento rapido in C

Sebbene il valore più a destra sia stato scelto per ogni sotto-list sopra, convenzionalmente, è il valore più a sinistra che viene scelto. Anche quando viene fatta un'ipotesi più intelligente, il buon valore indovinato dovrà essere inserito nella posizione più a sinistra; e il valore sinistro che era lì sarà posto in qualche altra posizione appropriata (ancora nell'elenco).

Esistono quattro funzioni C con i nomi, Swap (), Pivot (), Partition () e QuickSort (). QuickSort (), la funzione, è codificato in modo ricorsivo e chiama le altre funzioni.

La funzione Swap ()
Questa funzione scambia due elementi di array, usando i loro indici. È:

void swap (char a [], int m, int n)
char temp = a [m];
A [m] = a [n];
A [n] = temp;

Una semplice funzione Pivot ()
Questa funzione sceglie tra l'elemento più a sinistra e l'elemento più destro dell'intero elenco dato. Mette il minore di entrambi nella posizione più a sinistra e più grande nella posizione più a destra. È:

void pivot (char a [], int a sinistra, int a destra)
if (a [a sinistra]> a [destra])
scambia (a, sinistra, a destra);

Questo è meglio della semplice scelta dell'elemento più giusto per l'elenco e i sotto-listi, come fatto sopra. Di seguito è riportata una funzione Pivot () ancora migliore.

Una funzione di partizione ()
Proprio come la funzione Pivot () può essere scritta in diversi modi, la funzione di partizione () può essere scritta in modi diversi. Quello scelto per questo articolo è:

int partizione (char a [], int a sinistra, int a destra)
int pivot = a [a sinistra];
int i = sinistra;
int j = a destra + 1;
Fare
do ++ i;
mentre (un perno [i]);
se io < j)
scambia (a, i, j);
mentre io < j);
scambia (a, j, a sinistra);
ritorno j;

Dopo aver posizionato l'elemento pivot nella posizione più a sinistra dell'elenco o della sotto-list, dalla funzione pivot (), la funzione di partizione scansiona l'elenco o la sotto-list da entrambe le estremità, scambiando gli elementi che non sono sul lato corretto del perno. La scansione dall'estremità sinistra inizia dopo il perno dell'estremità più sinistra (dell'elenco o della sotto-list); Perché il perno verrà scambiato per ultimo ("do ++ i;" sopra).

L'indice di ritorno, J, è la nuova (successiva) posizione per pivot.

La funzione QuickSort ()
Questa è una funzione ricorsiva che chiama le altre funzioni. È:

void QuickSort (char a [], int a sinistra, int a destra)
Se (a sinistra < right)
Pivot (A, sinistra, a destra);
int k = partizione (a, sinistra, a destra);
QuickSort (A, a sinistra, K-1);
QuickSort (A, K+1, a destra);

Qui, K è lo stesso di J restituito sopra.

Tutte le funzioni di cui sopra codificate insieme, nell'ordine descritto, formeranno il programma QuickSort.

La funzione principale C

Una funzione principale C idonea per testare il programma è:

int main (int argc, char ** argv)

char a [] = "q", "w", "e", "r", "t", "y", "u", "i", "o", "p";
int sz = sizeof (a)/sizeof (a [0]);
QuickSort (A, 0, SZ-1);
per (int i = 0; iprintf ("%c", a [i]);
printf ("\ n");
restituzione 0;

La funzione QuickSort () è chiamata dalla funzione principale C, passando l'array come primo argomento. Il secondo argomento lasciato è un indice, 0, dell'intero elenco. Il terzo argomento, a destra, è l'ultimo ma uno dell'intero elenco.

Pivot mediano

Se tre numeri diversi sono disposti in ordine crescente, allora la mediana è il valore medio (secondo). Un modo migliore del precedente, per ottenere il perno, è cercare la mediana, tra il valore più a sinistra, il valore medio dell'elenco o la sotto-list e il valore più a destra. Il codice è:

int midindex = (sinistra + a destra) / 2; // Numero intero preso
if (a [midindex] < A[left])
scambiare (a, sinistra, midindex);
if (a [a destra] < A[left])
scambia (a, sinistra, a destra);
if (a [midindex] < A[right])
scambia (a, midindex, a destra);
char pivot = a [a destra];

Si noti che i tre elementi potrebbero aver cambiato posizione. Questo codice è combinato con la funzione Pivot () sopra per avere:

void pivot (char a [], int a sinistra, int a destra)
// Ottenere la mediana
int midindex = (sinistra + a destra) / 2; // Numero intero preso
if (a [midindex] < A[left])
scambiare (a, sinistra, midindex);
if (a [a destra] < A[left])
scambia (a, sinistra, a destra);
if (a [midindex] perno)
scambia (a, sinistra, a destra); // altrimenti, un [a sinistra] è il perno

Nota l'ultima condizione if.

Conclusione

Quick-Sort è un divario e conquista l'algoritmo di smistamento. Continua a dividere (partizionamento) l'elenco in tre sotto-listi in modo ricorsivo. La sotto-list centrale è sempre costituita da un elemento, che è il perno. Nel fare il perno, l'ordinamento viene eseguito in senso lato in quella fase. Tuttavia, man mano che la ricorsione continua, la selezione perfetta si ottiene alla fine del programma.