Ingegneria civile e strutturale
Come conteggio Sort ottimizza la selezione di piccole gamme di Integer
Table of Contents
Introduzione alla Contea
Counting Sort è un algoritmo di selezione basato su non-comparison che eccelle quando si selezionano interi su una piccola e conosciuta gamma. A differenza di tipi basati su confronti come Quicksort o Mergesort, che si basano su comparazioni di elementi a due sensi, Counting Sort determina l'ordine di dominio ordinato contando la frequenza di ogni valore distinta.
L'algoritmo è stato descritto per la prima volta da Harold H. Seward nel 1954 e rimane una tecnica fondamentale nella scienza del computer. La sua semplicità ed efficienza lo rendono ideale per compiti come la selezione di età studentesca, voti, o qualsiasi dato interi con una diffusione modesta.
Come Contare le Opere Ordinate
Il meccanismo centrale di Counting Sort è semplice: conta quante volte ogni valore appare nell'array di input, quindi utilizza che contano per calcolare la posizione finale di ogni elemento.
- Contatta:[]] Creare una serie di conteggi di dimensione k (la gamma di valori di input), inizializzato a zero.
- Prefissi di calcolo:[] Trasformare l'array di conteggio in una somma di prefisso, dove ogni elemento indice detiene il conteggio cumulativo di elementi inferiori o uguali a i. Questo passaggio determina le posizioni di partenza per ogni valore distinto nell'output ordinato.
- Elementi di posizionamento:[] Traversare l'array di input da destra a sinistra (per stabilità), utilizzare l'array di conteggio per trovare l'indice corretto nell'array di uscita, posizionare l'elemento e decrementare il conteggio. L'output finale è una copia ordinata dell'ingresso.
L'algoritmo restituisce una nuova matrice ordinata, lasciando l'originale invariato. Esiste una variante chiamata [ in-place Counting Sort[] ma raramente viene utilizzata perché compromette stabilità o efficienza spaziale.
Esempio di passo-passo
Considerare la selezione della matrice [4, 2, 2, 8, 3, 1][]] dove i valori variano da 0 a 8.
- Contegno:] Conteggio array dimensione 9 (0–8) → [0,1,2,1,0,0,1]. (Index 1 appare una volta, indice 2 due volte, indice 3 due volte, indice 4 una volta, indice 8 una volta).
- Prefisso somma:[[]] Trasformare in cumulativo → [0,1,3,5,6,6,6,7]. Ora ogni valore ci dice la posizione di partenza per quel numero in uscita ordinata.
- Output:[] Traverso array originale da fine: primo elemento letto è 1 → posizione = conteggio[1] - 1 = 0 → output[0]=1, conteggio di decremento[1] a 0. Il prossimo è 3 → posizione = conteggio[3] - 1 = 4 → output[4]=3, conte[3]=4. Continua fino a tutti gli elementi posti. Uscita finale: [1,2,2,3,4,8]
Questo esempio dimostra come Counting Sort evita completamente i confronti, basandosi esclusivamente sulle operazioni aritmetiche.
Complessità computazionale
Complessità del tempo
- Migliore, media e peggiore caso:[ O(n + k), dove n è il numero di elementi e k è la gamma di valori di input. Quando k è piccolo rispetto a n, l'algoritmo funziona in tempo lineare.
- Comparison a confronti di tipi:[ Quicksort e Mergesort hanno O(n log n) complessità media. Per n = 106 e k = 1000, Counting Sort (≈ 1,001,000 operazioni) è circa 13 volte più veloce di una tipica O(n log n) sorta.
Complesso spaziale
- Primario:[] O(k) per l'array di conteggio, più O(n) per l'array di uscita. Questa memoria può essere proibitiva se k è grande (ad esempio, ordinando integer a 32 bit dove k = 232).
- Variante stabile:[] Richiede una serie di uscite ausiliarie di dimensioni n; varianti in-place sacrificano stabilità o usano la manipolazione complessa dell'indice.
Quando usare il conteggio
Counting Sort è più efficace nelle seguenti condizioni:
- L'ingresso è costituito da interi (o dati che possono essere mappati a una piccola gamma di interi, come caratteri o categorie discrete).
- La gamma k non è significativamente più grande di n. Una regola comune di pollice è k ≤ O(n).
- La memoria non è fortemente limitata, perché l'array di conteggio e il buffer di uscita richiedono spazio extra.
- La stabilità è necessaria (ad esempio, la selezione da più chiavi) e l'implementazione standard è stabile quando gli elementi vengono posizionati da destra a sinistra.
I casi di utilizzo eccellenti includono i gradi di selezione (0–100), le età (0–120), le categorie di prodotto (fino a poche centinaia di SKU), o come subroutine in [Radix Sort.
Limitazioni e considerazioni
Nonostante la sua velocità, Counting Sort ha svantaggi che limitano la sua applicabilità:
- Integer solo:[ Non può ordinare direttamente numeri o stringhe a punti fluttuanti a meno che non vengano convertiti in un insieme interico contiguo.
- Grande gamma:[] Se k nani n—ad esempio, selezionando 100 numeri con valori tra 1 e 107—il conteggio array consuma enorme memoria mentre si ordina solo pochi elementi.
- Non-adaptive:[]] Counting Sort richiede sempre la scansione dell'intero input e la costruzione dell'array di conteggio, anche se i dati sono già ordinati o quasi ordinati.
- Valori negativi:[] La Standard Counting Sort assume interi non negativi. Per gestire i negativi, è possibile spostare i valori sottraendo il minimo (facendo la gamma da 0 a max – min).
Queste limitazioni significa Counting Sort è uno strumento specializzato, non un sostituto universale per algoritmi di uso generale.
Confronto con Algoritmi di Ordinazione Correlati
Contare il tipo vs. Radix Ordina
Radix Sort estende l'idea selezionando cifre da meno significative a più significative, utilizzando una sorta stabile (spesso Counting Sort) a ciascuna cifra. Mentre Counting Sort lavora su un passaggio sopra la gamma completa k, Radix Sort esegue più passaggi su una gamma di cifre più piccola (ad esempio, base 256), riducendo l'utilizzo della memoria per grandi k. Ad esempio, selezionando integer a 32 bit con Counting Sort2 solo richiede una serie di conteggio di 23 cifre.
Contare il Sort vs. Bucket
La serie di Bucket distribuisce elementi in una serie di secchi e ordina ogni secchio singolarmente (spesso con inserimento). La selezione di conteggio può essere considerata come un caso speciale di Bucket Sort dove ogni secchio corrisponde a un unico valore distinto.
Implementazione di un conteggio stabile
La stabilità è importante quando si seleziona una chiave mantenendo l'ordine relativo di elementi uguali da un'altra chiave. L'algoritmo standard Counting Sort è intrinsecamente stabile quando il loop di posizionamento dell'uscita attraversa l'ingresso da destra a sinistra.
- Computare la matrice di conteggio come descritto.
- Converti in somma prefissa (posizioni di ogni valore nell'output ordinato).
- Iterare l'array di input in ordine inverso. Per ogni elemento, posizionarlo nella posizione indicata dal suo conteggio, quindi decrement che conta.
Poiché trattiamo gli elementi dalla fine, l'ultima occorrenza di un dato valore va nel più alto indice possibile, mantenendo l'ordine relativo.Questa versione stabile è essenziale per Radix Sort per funzionare correttamente su ogni cifra.
Applicazioni pratiche
- Sistemi di grading educativi:[[] Ordinare centinaia di punteggi di esame (range 0–100) in O(n) tempo.
- Bioinformatics:[] Ordinare le frequenze di lettura integer o di DNA k‐mer quando la dimensione dell'alfabeto è piccola (A, C, G, T).
- Manutenzione indice Database:[] Ordinare identificatori interi univoci in un intervallo abbastanza piccolo da adattarsi alla memoria.
- Image processing:[] Ordinare i contenitori di istogramma o le intensità di colore (0–255) quando si costruiscono tavolini di ricerca.
- Sorting by second key:[] Usato all'interno di Radix Sort, che è il cavalletto di lavoro per una selezione efficiente in molte librerie e lingue (ad esempio, il runtime .NET utilizza un mix adattativo di algoritmi, tra cui Counting Sort per piccole gamme).
Per ulteriori informazioni sulla teoria e sulle varianti, consultare riferimenti autorevoli come []Wikipedia: Counting Sort e []GeeksforGeeks: Counting Sort.
Ottimizzazione di Conteggio Ordina per Grandi Gamma
Quando k è grande ma n è anche grande, puro Counting Sort diventa memoria-intensivo. Esistono diverse ottimizzazioni:
- Radicità compressa:[] Usare una mappa hash invece di una matrice contigua quando la gamma dei valori utilizzati è grande, ma il numero di valori distinti è piccolo. Questo commercio indicizzazione costante-tempo per schiantare la testa, ma riduce il consumo di memoria.
- Hybrid si avvicina:[] Combinare il conteggio Ordina con altri algoritmi. Ad esempio, se l'intervallo supera 106, utilizzare Radix Sort con una base che mantiene piccoli intervalli di cifre.
- Varianti di posizione:[] Alcune ottimizzazioni riducono lo spazio extra a O(k) senza un array di output, ma generalmente sacrificano la stabilità o richiedono cicli per individuare le posizioni.
Conclusioni
CountLTS(S) è un algoritmo estremamente efficiente per ordinare gli interi quando l'intervallo di valore è piccolo rispetto al numero di elementi. La sua complessità temporale O (n + k) e le prestazioni lineari lo rendono indispensabile in scenari come la selezione di grado, Radix Sort subroutines, e applicazioni con chiavi integre limitate. Tuttavia, la dipendenza dell'algoritmo da input interi e la sua memoria overhead per grandi intervalli ci ricorda che non è