Shelli sortimine

Allikas: Vikipeedia
Shelli sortimine
Shelli sortimine sammhaaval
Shelli sortimine sammudega 23, 10, 4, 1
Algoritmi liik Sortimisalgoritm
Ajaline keerukus halvimal juhul O(n2) (halvima sammujadaga)
O(n log2n) (parima teadaoleva sammujadaga)
Ajaline keerukus keskmiselt sõltub sammude jadast
Ajaline keerukus parimal juhul O(n log n) (enamus sammujadasid)
O(n log2n)
Mahuline keerukus О(n)

Shelli sortimine (ka väheneva sammu meetod) on sortimisalgoritm, mis töötab kohapeal (s.t. ei vaja abiandmestruktuure) ja põhineb elementide võrdlusel. Shelli sortimisalgoritmi vaadeldakse tavaliselt pistemeetodi variatsioonina, kus võrreldakse ja vahetatakse ka üksteisest kaugel asuvaid elemente.[1]

Algoritmi käigus sorditakse esmalt elemendid, mis asuvad üksteisest suure fikseeritud sammu kaugusel, seejärel vähendatakse järk-järgult sorditavate elementide vahelist sammu. Suure sammuga alustamine võimaldab mõned elemendid viia oma õigele positsioonile kiiremini kui ainult kõrvuti asuvate elementide vahetamine.[1]

Algoritmi esimese versiooni avaldas Donald Shell 1959. aastal.[2]

Kirjeldus[muuda | muuda lähteteksti]

Shelli sortimise idee seisneb loendi elementide ümberpaigutamises nii, et võttes mistahes positsioonist alustades iga h-nda elemendi, saadakse sorditud alamloend. Sel juhul öeldakse, et loend on h-sorditud.[1] Suurte h väärtustega alustamine võimaldab liigutada elementide kaugetele positsioonidele, vähendades kiiresti valejärjestusi. Kui loend on k-sorditud mingi täisarvu k < h korral, siis loend jääb ka h-sordituks.[3] Vähendades sammu h arvuni 1, saadakse tulemuseks alati sorditud loend.[1]

Alljärgnev on näide Shelli sortimisest sammudega 5, 3 ja 1.

a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12
Algne loend 62 83 18 53 07 17 95 86 47 69 25 28
5-sorditud 17 28 18 47 07 25 83 86 53 69 62 95
3-sorditud 17 07 18 47 28 25 69 62 53 83 86 95
1-sorditud 07 17 18 25 28 47 53 62 69 83 86 95

Esimesel läbimisel sorditakse pistemeetodil alamloendid, mille elementide indeksid algses loendis erinevad 5 võrra: (a1, a6, a11), (a2, a7, a12), (a3, a8), (a4, a9), (a5, a10). Näiteks on alamloend (a1, a6, a11) ehk (62, 17, 25) pärast sortimist (17, 25, 62). Järgmisel läbimisel sorditakse alamloendid (a1, a4, a7, a10), (a2, a5, a8, a11), (a3, a6, a9, a12). Viimasel läbimisel sorditakse kogu loend (a1,..., a12) tavalise pistemeetodiga.

Näide illustreerib, kuidas Shelli sortimisel on alamloendid algul lühikesed ja hiljem pikad, kuid peaaegu sorditud. Mõlemal juhul töötab tavaline pistemeetod efektiivselt.[4]

Shelli sortimine ei ole stabiilne: võrdsete elementide korral võib nende omavaheline järjestus tulla erinev. Shelli sortimisalgoritm on adaptiivne ehk selle tööaeg on lühem loenditel, mis on juba osaliselt sorditud.

Pseudokood[muuda | muuda lähteteksti]

Koodis on kasutatakse Marcin Ciura sammude jada ja sisemise sortimismeetodina pistemeetodit.

# Olgu sorditavaks loendiks a[0...n-1].
gaps = [701, 301, 132, 57, 23, 10, 4, 1]

# Alustame suurima sammuga ja lõpetame sammuga 1.
foreach (gap in gaps)
{
    # Sordime üksteisest käesoleva sammu kaugusel asuvad elemendid.
    # Esimese sammu elemendid a[0..gap-1] on juba sammu järgi sorditud.
    # Lisame ühe elemendi kaupa, kuni kogu loend on sammu järgi sorditud.
    for (i = gap; i < n; i += 1)
    {
        # Lisame a[i] sammuga sorditud elementide hulka.
        # Salvestame a[i] abimuutujasse temp, et vabastada positsioon i.
        temp = a[i]
        # Nihutame varasemaid sammuga sorditud elemente, kuni leiame a[i] õige positsiooni.
        for (j = i; j >= gap and a[j - gap] > temp; j -= gap)
        {
            a[j] = a[j - gap]
        }
        # Paneme abimuutuja (originaalse a[i]) õigele positsioonile.
        a[j] = temp
    }
}

Sammujadad[muuda | muuda lähteteksti]

Shelli sortimisalgoritmi ajaline keerukus sõltub valitud sammupikkuste jadast.[5] Tõestatult parimat võimalikku sammujada ei ole leitud.[1] Iga sammujada, mis lõpeb sammuga 1, annab Shelli sortimise tulemuseks korrektselt sorditud loendi.

Alljärgnev tabel võrdleb levinumaid seni avaldatud sammujadasid. Mõned neist on kasvavad lõpmatud jadad, mille elemendid, mis on väiksemad kui N, tuleb võtta vastupidises (kahanevas) järjekorras.

Jada üldliige (k ≥ 1) Konkreetsed sammud Halvima juhu ajaline keerukus Autor ja avaldamise aasta
[nt N = 2p korral] Shell, 1959[2]
Frank & Lazarus, 1960[6]
Hibbard, 1963[7]
, alates arvust 1 Papernov & Stasevich, 1965[8]
Järjestikused arvud kujul Pratt, 1971[9]
, mitte suurem kui Knuth, 1973,[3] eeskujuks Pratt, 1971[9]
Incerpi & Sedgewick, 1985,[10] Knuth[3]
, alates arvust 1 Sedgewick, 1982[1]
Sedgewick, 1986[11]
Teadmata Gonnet & Baeza-Yates, 1991[12]
Teadmata Tokuda, 1992[13]
Teadmata (eksperimentaalselt leitud) Teadmata Ciura, 2001[14]

Kui arvu N kahendesituses esineb palju järjestikuseid nulle, tehakse sortimisel Shelli originaalse sammujadaga halvimal juhul Θ(N2) võrdlust. Selline juht ilmneb näiteks siis, kui N on võrdne arvu 2 mingi astmega ja mediaanist suuremad elemendid on paaritutel positsioonidel ning väiksemad paaris positsioonidel, kuna siis võrreldakse neid alles viimasel läbimisel.

Keskmise võrdluste arvu poolest on teadaolevalt parima jõudlusega Ciura jada[14], kus sammupikkused üle 701 saab välja arvutada üldvalemiga .

Rakendused[muuda | muuda lähteteksti]

Shelli sortimine teeb rohkem võrdlusi ja sellel on suurem vahemälu möödalask kui kiirsortimisel, kuid selle implementatsioon on lühike ja see ei kasuta kutsepinu. Seetõttu on Shelli sortimine kasutusel mõnes qsort funktsiooni implementatsioonis C standardteegis, mis on suunatud manussüsteemidele. Sarnastel põhjustel oli Shelli sortimine varem kasutusel Linuxi kernelis.[15] Shelli sortimist võib kasutada introsort algoritmis, et sortida lühikesi alamloendeid ja vältida algoritmi aeglustumist, kui rekursioon saavutab teatud sügavuse. Sel põhimõttel töötab näiteks bzip2 kompressor.[16]

Viited[muuda | muuda lähteteksti]

  1. 1,0 1,1 1,2 1,3 1,4 1,5 Robert Sedgewick (1998). Algorithms in C (inglise). Kd 1 (3. trükk). Addison-Wesley. Lk 273–281. ISBN 978-0-201-31452-6.
  2. 2,0 2,1 Shell, D. L. (1959). "A High-Speed Sorting Procedure". Communications of the ACM (inglise). 2 (7): 30–32. DOI:10.1145/368370.368387. ISSN 0001-0782.
  3. 3,0 3,1 3,2 Donald E. Knuth (1997). The Art of Computer Programming. Volume 3: Sorting and Searching (2. trükk). Reading, Massachusetts: Addison-Wesley. Lk 83–95. ISBN 978-0-201-89685-5.
  4. Bharadwaj, Ashutosh; Mishra, Shailendra (2013). "Comparison of Sorting Algorithms based on Input Sequences" (PDF). International Journal of Computer Applications. 78 (14): 7–10. DOI:10.5120/13589-1325.
  5. Sedgewick, Robert (1996). "Analysis of Shellsort and Related Algorithms". Fourth European Symposium on Algorithms (inglise). DOI:10.1007/3-540-61680-2_42.
  6. Frank, R. M.; Lazarus, R. B. (1960). "A High-Speed Sorting Procedure". Communications of the ACM (inglise). 3 (1): 20–22. DOI:10.1145/366947.366957. ISSN 0001-0782.
  7. Hibbard, Thomas N. (1963). "An empirical study of minimal storage sorting". Communications of the ACM (inglise). 6 (5): 206–213. DOI:10.1145/366552.366557. ISSN 0001-0782.
  8. Papernov, A. A.; Stasevich, G. V. (1965). "A Method of Information Sorting in Computer Memories" (PDF). Problems of Information Transmission. 1 (3): 63–75.
  9. 9,0 9,1 Pratt, Vaughan R. (1979). Shellsort and sorting networks. New York: Garland Pub. ISBN 0-8240-4406-1.
  10. Incerpi, Janet; Sedgewick, Robert (1985). "Improved upper bounds on shellsort". Journal of Computer and System Sciences (inglise). 31 (2): 210–224. DOI:10.1016/0022-0000(85)90042-X.
  11. Sedgewick, Robert (1986). "A new upper bound for Shellsort". Journal of Algorithms (inglise). 7 (2): 159–173. DOI:10.1016/0196-6774(86)90001-5.
  12. Gonnet, G. H. (Gaston H.) (1984). Handbook of algorithms and data structures. London: Addison-Wesley Pub. Co. ISBN 0-201-14218-X.
  13. Tokuda, N. (1992). "An Improved Shellsort". Proceedings of the IFIP 12th World Computer Congress on Algorithms, Software, Architecture. Amsterdam: North-Holland Publishing Co. Lk 449–457.
  14. 14,0 14,1 Ciura, M. (2001). "Best Increments for the Average Case of Shellsort". Proceedings of the 13th International Symposium on Fundamentals of Computation Theory. London: Springer-Verlag. Lk 106–117. ISBN 978-3-540-42487-1.
  15. "kernel/groups.c". Vaadatud 7.12.2020.{{cite web}}: CS1 hooldus: url-olek (link)
  16. Julian Seward. "bzip2/blocksort.c". Vaadatud 7.12.2020.{{cite web}}: CS1 hooldus: url-olek (link)