A Counting sort [1] ( eng. counting sort [2] ; rendezés számlálással [3] eng. sorting by counting [4] ) egy rendezési algoritmus , amely egy rendezett tömb ( lista ) számtartományát használja az egyező elemek megszámlálására . A számláló rendezés használata csak akkor hasznos, ha a rendezett számoknak olyan lehetséges értéktartománya van (vagy leképezhető), amely elég kicsi a rendezett halmazhoz képest, például millió természetes szám 1000-nél kisebb.
Tegyük fel, hogy a bemeneti tömb egész számokból áll a -tól -ig terjedő tartományban , ahol . Továbbá az algoritmust egy tetszőleges egész tartományra általánosítjuk. A számlálási rendezésnek számos módosítása létezik, az alábbiakban három lineáris és egy kvadratikus, amely más megközelítést használ, de ugyanaz a neve.
Ez az algoritmus legegyszerűbb változata. Hozzon létre egy C[0..k]nullákból álló segédtömböt, majd olvassa be egymás után a bemeneti tömb elemeit, Amindegyikhez eggyel A[i]növelve C[A[i]]. Most elég végigmenni a tömbön C, mindegyik tömbbe egymás után írja be a j számot . AC[j]
SimpleCountingSort: ha i = 0-tól k-ig C[i] = 0; ha i = 0 - n - 1 C[A[i]] = C[A[i]] + 1; b = 0; j = 0-tól k-ig ha i = 0 - C[j] - 1 A[b] = j; b = b + 1;Megvalósítás C nyelven :
//tömb - mutató a tömb elejére //n - tömb mérete //k - maximális szám a tömbben void countingSort ( int * array , int n , int k ) { int * c = ( int * ) malloc (( k + 1 ) * sizeof ( * array )); memset ( c , 0 , sizeof ( * array ) * ( k + 1 )); for ( int i = 0 ; i < n ; ++ i ) { ++ c [ tömb [ i ]]; } int b = 0 ; for ( int i = 0 ; i < k + 1 ; ++ i ){ for ( int j = 0 ; j < c [ i ]; ++ j ) { tömb [ b ++ ] = i ; } } szabad ( c ); }Megvalósítás C++ nyelven :
#include <vektor> #include <type_traits> #include <algoritmus> sablon < típusnév std :: enable_if_t < std :: is_integral_v < T > , T >> void countingSort ( std :: vektor < T >& array ) { T max = std :: max_element ( array .begin (), array .end ( ) ); auto count = std :: vektor < T > ( max + 1 , T ( 0 )); for ( T elem : tömb ) ++ c [ elem ]; Tb = 0 ; _ for ( méret_t i = 0 ; i < max + 1 ; ++ i ) { for ( T j = 0 ; j < count [ i ]; ++ j ) { tömb [ b ++ ] = i ; } } }Ezt a változatot ( galamblyuk rendezés, számlálás rendezés ) akkor használjuk, ha a bemenet adatszerkezetek tömbje, amelyeket kulcsok ( key) szerint kell rendezni. Létre kell hoznia egy segédtömböt C[0..k - 1], C[i]amely később mindegyik tartalmazni fogja a bemeneti tömb elemeinek listáját. Ezután sorban olvassa be a bemeneti tömb elemeit , és Amindegyiket A[i]hozzáadja a listához C[A[i].key]. Végezetül menjen végig a tömbön C, minden tömbhöz írja be egymás után a lista elemeit . Az algoritmus stabil . AC[j]
ListCountingSort ha i = 0 - k - 1 C[i] = NULL; ha i = 0 - n - 1 C[A[i].key].add(A[i]); b = 0; j = 0 és k - 1 között p = C[j]; míg p != NULL A[b] = p.adatok; p = p.next(); b = b + 1;Ebben a változatban a bemeneti tömbön kívül Akét segédtömbre van szükség - C[0..k - 1]a számlálóhoz és B[0..n - 1]a rendezett tömbhöz. Először töltse fel a tömböt Cnullákkal, és minden egyes A[i]növelésnél C[A[i]]1-gyel. Ezután a -val kisebb vagy egyenlő elemek számát számolja a rendszer . Ehhez mindegyik , -tól kezdődően -val megnövelve . Így az utolsó cella a bemeneti tömbben lévő elemek számát tartalmazza majd . Az algoritmus utolsó lépésében a bemeneti tömb végétől beolvasásra kerül, az értéket 1-gyel csökkentjük, és . Az algoritmus stabil. C[j]C[1]C[j - 1]C[A[i]]B[C[A[i]]]A[i]
StableCountingSort ha i = 0 - k - 1 C[i] = 0; ha i = 0 - n - 1 C[A[i]] = C[A[i]] + 1; j = 1 és k - 1 között C[j] = C[j] + C[j-1]; ha i = n - 1-től 0-ig C[A[i]] = C[A[i]]-1; B[C[A[i]]] = A[i];Több kérdés is felmerül. Mi van, ha az értéktartomány (min és max) nem ismert előre? Mi van akkor, ha a minimális érték nagyobb nullánál, vagy negatív számok vannak a rendezett adatokban? Az első kérdés megoldható a min és max lineáris keresésével, ami nem befolyásolja az algoritmus aszimptotikáját. A második kérdés valamivel nehezebb. Ha a min nagyobb, mint nulla, akkor vonja ki a min értéket a tömbből, amikor a tömbbel dolgozik, és adja hozzá a min értéket, amikor visszaírja C. A[i]Ha vannak negatív számok, akkor hozzá kell Cadni A[i], ha tömböt használunk |min|, és ki kell vonni, ha visszaírunk.
Az elsõ két algoritmusban az elsõ két hurok a és -nek dolgozik ; dupla ciklus a . A harmadik algoritmusban a ciklusok rendre , , és . Összességében mindhárom algoritmus lineáris időbonyolultságú . Az első két algoritmusban használt memória , a harmadikban pedig .
A számláló rendezést kissé eltérő algoritmusnak is nevezik. Egy bemeneti tömböt Aés egy segédtömböt Bhasznál a rendezett halmazhoz. Az algoritmusban a bemeneti tömb minden eleméhez A[i]számolja meg a nála kisebb elemek számát és a vele megegyező, de korábban álló elemek számát ( ). hozzárendelni . Az algoritmus stabil. B[c]A[i]
SquareCountingSort ha i = 0 - n - 1 c = 0; j = 0-tól i-1-ig ha A[j] <= A[i] c = c + 1; ha j = i + 1 - n - 1 ha A[j] < A[i] c = c + 1; B[c] = A[i];Nyilvánvaló, hogy az algoritmus időbecslése: memória .
Egyszerű algoritmus.
ELJÁRÁS CountingSort ( VAR a : ARRAY OF INTEGER ; min , max : INTEGER ) ; VAR i , j , c : INTEGER ; b : POINTER AZ EGÉSZ SZÁM TÖMBRE ; BEGIN ASSERT ( min <= max ) ; ÚJ ( b , max - min + 1 ) ; FOR i := 0 TO LEN ( a ) - 1 DO INC ( b [ a [ i ] - min ]) VÉGE ; i := 0 ; FOR j := min TO max DO c := b [ j - min ] ; WHILE c > 0 DO a [ i ] := j ; INC ( i ) ; DEC ( c ) END END END CountingSort ;Rendezési algoritmusok | |
---|---|
Elmélet | Bonyolultság O jelölés Rendelési viszony Típusok rendezése fenntartható Belső Külső |
Csere | |
Választás | |
Betétek | |
egyesülés | |
Nincs összehasonlítás | |
hibrid | |
Egyéb | |
nem praktikus |