2010-10-08 11 views
22
 a=[1,3,6,7,1,2] 

Quale è la migliore tecnica di ordinamento per ordinare il seguente array e se ci sono duplicati su come gestirli. inoltre, che è la migliore tecnica di smistamento di tutti ....C Suggerimenti per lo smistamento di array

void BubbleSort(int a[], int array_size) 
{ 
int i, j, temp; 
for (i = 0; i < (array_size - 1); ++i) 
{ 
     for (j = 0; j < array_size - 1 - i; ++j) 
     { 
      if (a[j] > a[j+1]) 
      { 
       temp = a[j+1]; 
       a[j+1] = a[j]; 
       a[j] = temp; 
      } 
     } 
} 
} 
+1

Vedere: http://en.wikipedia.org/wiki/Sorting_algorithm – Donotalo

+2

Non esiste una "migliore tecnica di ordinamento di tutti", dipende dalla dimensione dei dati e se è un po 'ordinata all'inizio. Ti suggerisco di leggere http://en.wikipedia.org/wiki/Sorting_algorithm#Comparison_of_algorithms e anche l'intero articolo di Wikipedia. – schnaader

+0

"migliore" dipende dai dati e da altri vincoli: memoria, velocità, modalità di smistamento iniziale. quicksort è un ottimo compromesso tra quelli. bubble sort è il migliore per la memoria di piccole dimensioni. Cosa vuoi realizzare? – dawg

risposta

38

In C, è possibile utilizzare il costruito nel qsort comando:

int compare(const void* a, const void* b) 
{ 
    int int_a = * ((int*) a); 
    int int_b = * ((int*) b); 

    if (int_a == int_b) return 0; 
    else if (int_a < int_b) return -1; 
    else return 1; 
} 

qsort(a, 6, sizeof(int), compare) 

vedi: http://www.cplusplus.com/reference/clibrary/cstdlib/qsort/


Per rispondere alla seconda parte della domanda: un algoritmo di ordinamento ottimale (basato su confronto) è uno che viene eseguito con confronti O (n log (n)). Ce ne sono diversi che hanno questa proprietà (compresi l'ordinamento rapido, l'ordinamento di unione, l'ordinamento dell'heap, ecc.), Ma quale da usare dipende dal caso d'uso.

Come nota a margine, si può a volte fare meglio di O (n log (n)) se si sa qualcosa circa i dati - vedi l'articolo Wikipedia sul Radix Sort

+4

@Alex: se lo vuoi veloce, fornisci almeno una funzione di confronto decente! qsort non ha bisogno che i valori restituiti siano -1, 0, 1, ma "qualsiasi numero negativo", 0, "qualsiasi numero positivo", quindi devi solo fare "return * ((int *) a) - * ((int *) b); 'che è molto più veloce della tua proposta. – kriss

+5

@kriss: il confronto non è ben definito in caso di overflow di interi; quindi, spesso si vedono cose come 'return (a> b) - (a Christoph

+0

@kriss: tranne che la funzione di confronto non funziona (necessariamente). Cosa succede se 'a' è' INT_MAX' e 'b' è' -1', per esempio? –

11

Nel tuo caso particolare, il tipo più veloce è probabilmente quello descritto in this answer. È esattamente ottimizzato per un array di 6 pollici e utilizza reti di smistamento. È 20 volte (misurato su x86) più veloce della libreria qsort. Le reti di ordinamento sono ottimali per tipi di matrici a lunghezza fissa. Poiché sono una sequenza fissa di istruzioni, possono persino essere implementate facilmente dall'hardware.

In generale esistono numerosi algoritmi di ordinamento ottimizzati per casi specifici. Gli algoritmi di uso generale come heap sort o quick sort sono ottimizzati per l'ordinamento in loco di una serie di elementi. Forniscono una complessità di O (n.log (n)), n è il numero di elementi da ordinare.

La funzione di libreria qsort() è molto ben codificato ed efficiente in termini di complessità, ma utilizza una chiamata a una funzione comparizon fornito dall'utente, e questa chiamata ha un costo piuttosto elevato.

Per l'ordinamento di una grande quantità di dati gli algoritmi devono anche occuparsi dello scambio di dati da e verso il disco, questo è il tipo di ordinamento implementato nei database e la soluzione migliore se si hanno tali esigenze è mettere i dati in alcuni database e utilizzare l'ordinamento incorporato.

+0

+1 per l'ordinamento delle reti –

5

Depends

Dipende da varie cose. In generale, tuttavia, gli algoritmi che utilizzano un approccio Divide-and-Conquer/dichotomic si comportano bene per problemi di ordinamento in quanto presentano interessanti complessità del caso medio.

Basics

per capire quali algoritmi funzionano meglio, avrete bisogno di conoscenza di base di algorithms complexity e big-O notation, in modo da poter capire come si valutano in termini di average case, best case and worst case scenarios. Se necessario, dovresti anche prestare attenzione allo sorting algorithm's stability.

Ad esempio, in genere un algoritmo efficiente è quicksort. Tuttavia, se si fornisce a quicksort una lista perfettamente invertita, allora avrà un rendimento scarso (un ordinamento di selezione semplice avrà un rendimento migliore in tal caso!). Shell-sort sarebbe anche di solito un buon complemento a quicksort se si esegue una pre-analisi del proprio elenco.

dare un'occhiata a quanto segue, per "le ricerche avanzate" utilizzando divide et impera approcci:

E questi algoritmi più straighforward per meno quelli complessi:

Ulteriori

Quanto sopra sono i soliti noti Quando si comincia, ma ci sono innumerevoli altri.

Come indicato da R. nei commenti e da kriss nella sua risposta, si consiglia di dare un'occhiata a HeapSort, che fornisce una complessità di ordinamento teoricamente migliore di un quicksort (ma non sarà spesso meglio in impostazioni pratiche). Esistono anche varianti e hybrid algorithms (ad esempio TimSort).

+0

Se si fornisce un elenco perfettamente invertito a quicksort, esso degenererà solo nell'implementazione più ingenua (tutti prendono il sopravvento sulla lista come pivot) e anche allora non sarà peggio di BubbleSort. L'ingenuo Quicksort si comporterebbe male con una lista già ordinata. Ma le modifiche molto semplici all'algoritmo sono sufficienti per evitare il problema (estrarre diversi numeri dalla lista come potenziale perno e scegliere la mediana come pivot). – kriss

+0

@kriss: corretto. Ma questa è una domanda di apprendimento di CS, e quindi parlo solo dell'implementazione teorica e di base di ognuno di questi approcci. Ovviamente è possibile modificare gli algoritmi e minimizzare questi effetti collaterali, ma poiché l'OP sta chiedendo problemi di ordinamento generale, penso che sia più in linea individuare questi problemi. – haylem

+0

@haylem: probabilmente si tratta di una domanda di apprendimento, ma il rischio di implementazioni ingenue è che il lettore creda che la chiamata alla libreria qsort sia un'implementazione ingenua di QuickSort, che non è, e degenererebbe in un set di dati ordinato. Se ricordo bene, non è nemmeno un QuickSort nella maggior parte delle implementazioni. – kriss

1

vorrei apportare alcune modifiche: In C, è possibile utilizzare il costruito nel qsort comando:

int compare(const void* a, const void* b) 
{ 
    int int_a = * ((int*) a); 
    int int_b = * ((int*) b); 

    // an easy expression for comparing 
    return (int_a > int_b) - (int_a < int_b); 
} 

qsort(a, 6, sizeof(int), compare) 
2

La tecnica migliore di smistamento di tutto dipende generalmente coincide con la dimensione di un array. Unisci sort può essere il migliore di tutti in quanto gestisce una maggiore complessità di spazio e tempo secondo l'algoritmo Big-O (questo si adatta meglio a un array di grandi dimensioni).

Problemi correlati