Sortowanie bąbelkowe """"""""""""""""""""""" Algorytm połowienia przedziału zakładał, że wejściowa tablica liczb jest *posortowana*. Posortowanie listy w Pythonie jest bardzo proste: piszemy ``moja_lista.sort()`` i już ... lista jest posortowana. Warto jednak zapoznać się z działaniem algorytmów sortujących. W tej części omówimy jeden z najprostszych alrotymów - sortowanie bąbelkowe. Nie jest to wcale *najszybsza* metoda, przedstawiam ją tu głównie ze względów dydaktycznych. W metodzie bąbelkowej mamy dwie pętle: zewnętrzna pętla działa doputy, dopóki tablica nie jest posortowana. Pętla wewnętrzna przechodzi zaś po całej tablicy i porównuje parami sąsiednie elementy. Jeżeli element *wcześniejszy* ``tabl[i-1]`` jest większy od *kolejnego* ``tabl[i]``, to są one zamieniane miejscami. Dodatkowo zapamiętujemy, że dokonaliśmy zamiany i tablica może nie być posortowana - ustawiamy flagę ``is_sorted`` na ``False``. Zmusi to zewnętrzną pętlę ``while`` do jeszcze jednej iteracji, w której pętla ``for`` jeszcze raz sprawdzi wszystkie sąsiadujące pary. Jeżeli tym razem nie dokona żadnej zamiany, flaga ``is_sorted`` pozostanie ``True`` i program zakończy działanie. .. raw:: html
Załóżmy teraz, że *elementarną operacją* algorytmu jest sprawdzenie czy trzeba dokonać zamiany (i ew. zamiana elementów miejscami). Zastanów się teraz, ile takich operacji wykona ten program dla tablicy zawierającej ``N`` liczb? W pesymistycznym przypadku, kiedy tablica jest posortowana majeląco, będziemy musieli dokonać :math:`N^2/2` operacji zamiany. Dlatego powiemy, że ten algorytm ma *złożoność kwadratową* w przypadku pesymistycznym, co w *notacji wielkiego O* oznaczamy :math:`\mathcal{O}(N^2)` (czyt. *o-en-kwadrat*) .. admonition:: Praca domowa :class: def Jaka jest złożoność tego algorytmu w przypadku *optymistycznym*? Czyli - ile operacji porównań musimy wykonać, kiedy na wejściu programu jest tablica ``N`` liczb już posortowanych?