Sortiranje mehurom

Из Википедије, слободне енциклопедије
Sortiranje mehurom
Vizuelna predstava bablsort algoritma
Klasa Algoritam sortiranja
Struktura podataka Niz
Najgora performanca
Najbolja performanca
Prosečna performanca
Najgora prostorna kompleksnost

Sortiranje mehurom ili Bablsort (engl. Bubble sort), ponekad pogrešno nazvano potapajuće sortiranje, algoritam je koji se koristi za sortiranje nizova. Algoritam radi tako što upoređuje svaka dva susedna člana niza i zamenjuje im mesta, ako su članovi niza u pogrešnom redosledu. Prolazi se kroz niz elemenata sve dok se ne izvrši nijedna zamena tj. elementi su sortirani u odgovarajućem poretku (rastućem ili opadajućem). Naziv vodi poreklo od činjenice da se posle prve iteracije kroz niz najveći element nalazi na najvećoj poziciji u nizu, tj. na desnoj strani niza. Algoritam je veoma lak za implementaciju u svim programskim jezicima, ali je veoma nepraktičan i spor čak i kada se uporedi sa algoritmom kao što je sortiranje umetanjem.[1] Algoritam radi dobro na nizovima koji ima mali broj elemenata, ili koji su polusortirani, tj. samo određeni broj elemenata je na nepravilnim pozicijama.

Analiza[уреди]

Primer bubble sorta. Polazi se od početka niza, uproredjuje svaki susedni par i menja njihov položaj, ako nisu u pravom redosledu (sledeći je manji od prethodnog). Posle svake iteracije, upoređuje se jedan element manje, sve dok više ne postoje elementi koje treba upoređivati.

Performanse[уреди]

Bablsort ima najgoru složenost О(n2), gde je n broj elemenata koji se sortiraju. Postoji mnogo algoritama za sortiranje koji imaju znatno bolju složenost O(n log n). Čak i drugi algoritimi složenosti О(n2), kao što je sortiranje umetanjem, imaju tendenciju da imaju bolje performanse od bablsorta. Dakle, sortiranje mehurom nije praktičan algoritam za sortiranje kada je n veliko.

Jedina značajna prednost bablsorta za razliku od drugih implementacija, čak i kviksorta, ali ne sortiranja umetanjem, je sposobnost da otkrije da je sortiran niz efikasno ugrađen u algoritam. Složenost bablsorta nad već sortiranim nizovima (u najboljem slučaju) je O(n). Nasuprot tome, većina drugih algoritama, čak i oni sa boljom prosečnom složenošću, obavljaju ceo proces sortiranja na setu i na taj način su složeniji. Međutim, ne samo da insertion sort ima ovaj mehanizam, već i bolje radi na nizu koji je znatno sortiran (mali broj inverzija)

Zečevi i kornjače[уреди]

Pozicije elemenata u bablsortu igraju veliku ulogu u određivanju složenosti. Veliki elementi na početku niza ne predstavljaju problem jer se brzo zamene. Mali elementi pri kraju niza se kreću na početak veoma sporo. Zbog toga se ove vrste elemenata respektivno nazivaju zečevi i kornjače.

Učinjeni su razni napori da se eliminišu kornjače kako bi se poboljšala brzina bablsorta. Koktelsort je dvosmerni bablsort koji ide od početka do kraja, a onda se poništava i ide od kraja do početka. On može da se pomera kornjače prilično dobro, ali zadržava složenost O(n2). Kombsort poredi elemente razdvojene velikim prazninama, a može da pomera kornjače izuzetno brzo pre nego što pređe na manje praznine. Njegova prosečna brzina se može uporediti sa brzim algoritmima kao što je kviksort.

Korak po korak primer[уреди]

Niz brojeva "5 1 4 2 8" potrebno je sortirati od najmanjeg do najvećeg broja (u rastućem poretku) pomoću bablsorta. U svakom koraku boldirani elementi se upoređuju. Biće potrebna tri prolaska kroz niz:


Prvi prolazak:

(5 1 4 2 8 ) (1 5 4 2 8 ), Algoritam upoređuje prva dva elementa i zamenjuje 1 i 5 , 5 > 1.

(1 5 4 2 8 ) (1 4 5 2 8 ), zamena pošto je 5 > 4

(1 4 5 2 8 ) (1 4 2 5 8 ), zamena pošto je 5 > 2

(1 4 2 5 8 ) (1 4 2 5 8 ), Sada, pošto su ovi elementi već sortirani (8 > 5), algoritam ih neće zameniti.

Drugi prolazak:

(1 4 2 5 8 ) (1 4 2 5 8 )

(1 4 2 5 8 ) (1 2 4 5 8 ), zamena pošto je 4 > 2

(1 2 4 5 8 ) (1 2 4 5 8 )

(1 2 4 5 8 ) (1 2 4 5 8 )

Sada, niz je već sortiran, ali naš algoritam još uvek ne zna da je sortiranje završeno. Algoritam je završen tek kada prodje kroz ceo niz bez i jedne zamene.

Treći prolazak:

(1 2 4 5 8 ) (1 2 4 5 8 )

(1 2 4 5 8 ) (1 2 4 5 8 )

(1 2 4 5 8 ) (1 2 4 5 8 )

(1 2 4 5 8 ) (1 2 4 5 8 )

Implementacija[уреди]

Pseudokod implementacija[уреди]

Algoritam se može izraziti kao (0- bazni niz):

procedure bubbleSort(A : list of sortable items )
   repeat     
     swapped = false
     for i = 1 to length(A) - 1 inclusive do:
       /* if this pair is out of order */
       if A[i-1] > A[i] then
         /* swap them and remember something changed */
         swap(A[i-1], A[i] )
         swapped = true
       end if
     end for
   until not swapped
end procedure

Da podsetimo, postoje bolji algoritmi za sortiranje kao što je kviksort koji se obično koriste, a većina programskih jezika ima ugrađenu funkciju u standardnoj biblioteci koja se može koristiti umesto da se implementira sopstveni algoritam za sortiranje.

Optimizacija bubble sorta[уреди]

Bablsort algoritam se može lako opimizovati posmatranjem, ako se uoči da n-ti prolaz pronalazi n-ti najveći element i stavlja ga na njegovo mesto. Dakle, unutrašnja petlja može da se izbegne gledajući poslednjih n-1 elemenata kada radi za n-ti put:

procedure bubbleSort(A : list of sortable items )
    n = length(A)
    repeat
       swapped = false
       for i = 1 to n-1 inclusive do
          if A[i-1] > A[i] then
             swap(A[i-1], A[i])
             swapped = true
          end if
       end for
       n = n - 1
    until not swapped
end procedure

Uopšteno, može se desiti da se više od jednog elementa nalazi u završnoj poziciji u jednom prolazu. Konkretno, posle svakog prolaza, svi elementi do poslednje zamene su sortirani i ne treba ih ponovo proveravati. To nam omogućava da se presoči mnogo elemenata, što dovodi do u najgorem slučaju 50% poboljšanja i dodaje malo složenosti, jer novi kod podvodi „zamenljiva” promenljiva:


Da bi se ovo postiglo u pseudokodu pišemo sledeće:

procedure bubbleSort(A : list of sortable items )
    n = length(A)
    repeat
       newn = 0
       for i = 1 to n-1 inclusive do
          if A[i-1] > A[i] then
             swap(A[i-1], A[i])
             newn = i
          end if
       end for
       n = newn
    until n = 0
end procedure

Alternativne modifikacije, kao što je koktel sortiranje metoda pokušaji su da se poboljša bubble sort zadržavajući istu ideju (više puta se prede elementi i zamena susednih elemenata)

U praksi[уреди]

Bablsort, algoritam za sortiranje koji stalno prolazi kroz niz, zamenjuje mesta elementima dok se ne pojave u ispravnom redosledu. Treba zapaziti da se prvo sortiraju najveći elementi, a zatim manji.

Iako je bablsort jedan od najjednostavnijih algoritama za sortiranje potrebno je razumeti i njegovu primenu. Njegova složenost O(n2) znači da se njegova efikasnost smanjuje dramatično na nizovima koji imaju veći broj elemenata. Čak i među jednostavnim O(n2) algoritmima, algoritmi poput sortiranja umetanjem su znatno efikasniji.

Zbog svoje jednostavnosti, bablsort se često koristi da se uvede koncept algoritama ili algoritam za sortiranje na uvodnim predavanjima studentima informatika. Međutim, neki istraživači kao što je Oven Astračan su otišli predaleko omalovažavajući bablsort i njegovu popularnost u obrazovanju informatičara preporučujući da se više i ne uči.[2]

The Jargon file, čiji je poznati naziv glupi sort "the archetypical [sic] perversely awful algorithm", takođe naziva bablsort generički loš algoritam.[3] Donald Knut u svojoj čuvenoj knjizi Umetnost računarskog programiranja zaključio je da se Bablsort nema po čemu preporučiti osim po privlačnom imenu i činjenici da ne ispoljava neke od zanimljivih teorijskih problema o kojim je on tada govorio.[1]

Bablsort je asimptotski ekvivalentan sortiranju umetanjem po vremenu izvršavanja u najgorem slučaju, ali ova dva algoritma se veoma razlikuju po broju potrebnih zamena (svapova). Eksperimentalni rezultati kao što su oni od Astračana su takođe pokazali da sortiranje umetanjem radi znatno bolje čak i na slučajnim listama. Iz tih razloga mnogi moderni udžbenici izbegavaju korišćenje algoritma bablsorta u korist sortiranja umetanjem.

Bablsort takođe slabo komunicira sa modernim CPU hardverom. To zahteva najmanje duplo više pisanja nego kod insertion sorta, duplo vise keša, više filijala. Eksperimenti za Astračan sortiranje stringova u Javi pokazuje da algoritam mehura može da bude oko 5 puta sporiji od algoritma sa umetanjem i 40% sporiji od selekcionog sortiranja.[2]

U kompjuterskoj grafici je popularan zbog njegove sposobnosti da otkrije veoma malu grešku (kao zamenu samo dva elementa) u skorosortiranim nizovima i popraviti je sa linearnom složenošću (2n).

Varijacije[уреди]

  • Sortiranje "par-nepar" je paralelna verzija bablsorta, za sisteme razmene poruka.
  • Koktel sortiranje je paralelna verzija bablsorta.
  • U nekim slučajevima, sortiranje se vrši sa desna na levo (u suprotnom smeru) koji je pogodniji za delimično sortirane nizove, odnosno nizove sa nesortiranim elementima na kraju.

Pogrešan naziv[уреди]

Bablsort se pogrešno naziva potapajuće sortiranje. Potapajuće sortiranje je ispravan pseudonim za sortiranje sa umetanjem. Ova greška je uglavnom nastala kad je Nacionoalni institut za standarde i tehnologiju naveo taj pseudonim za bablsort. U knjizi Donalda Knuta „Umetnost kompjuterskog programiranja“, tom 3: sortiranja i pretrage, on navodi u odeljku 5.2.1 „sortiranje metodom umetanja rešava problem na svom pravom nivou“.

Reference[уреди]

  1. 1,0 1,1 Knuth, Donald (1998). The Art of Computer Programming, section 5.2.2: Sorting by Exchanging. 3: Sorting and Searching (Second изд.). Addison-Wesley. стр. 106—110. ISBN 0-201-89685-0. »"[A]lthough the techniques used in the calculations [to analyze the bubble sort] are instructive, the results are disappointing since they tell us that the bubble sort isn't really very good at all. Compared to straight insertion […], bubble sorting requires a more complicated program and takes about twice as long!" (Quote from the first edition, 1973.)« 
  2. 2,0 2,1 Owen Astrachan. Bubble Sort: An Archaeological Algorithmic Analysis. SIGCSE 2003 Hannan Akhtar . (pdf)
  3. jargon, node: bogo-sort

Literatura[уреди]

Spoljašnje veze[уреди]