← Lekcje
Python · lekcja 26

Bąbelkowe i przez wstawianie

Sortowanie liczb i wyszukiwanie, część 3 z 3

  1. Specyfikacja problemu: co dostajemy i co ma wyjść
  2. Sortowanie bąbelkowe: prosta zamiana, przykład, funkcja bubble_sort
  3. Sortowanie przez wstawianie: tak jak układacie karty w ręku
  4. Ile porównań i zamian kosztuje uporządkowanie listy?

Podręcznik: s. 139–148.

Rozgrzewka · 3 minuty

Po co komu porządek?

Wracamy do poprzedniej lekcji, tej o wyszukiwaniu sekwencyjnym i binarnym.

  1. Wyszukiwanie sekwencyjne sprawdza komórki po kolei, od pierwszej. Co robi zamiast tego wyszukiwanie binarne?
  2. Wyszukiwanie binarne działa tylko wtedy, gdy zbiór spełnia jeden warunek. Jaki to warunek?
  3. Uporządkowanie danych kosztuje czas. Dlaczego mimo to często się opłaca?
podręcznik s. 133–139
Część 1 · Problem sortowania

Porównaj sąsiadów i zamień

Porządkowanie (sortowanie) to problem, dla którego opisano co najmniej kilkanaście algorytmów. Żaden z nich nie jest najszybszy w każdej sytuacji. Zaczynamy od najprostszego.

Sortowanie bąbelkowe (ang. bubble sort) porównuje parę sąsiednich elementów, zaczynając od pierwszej pary na liście, i zamienia je miejscami, gdy stoją w niewłaściwej kolejności. Taka zamiana sąsiadów to operacja prostej zamiany, dlatego metodę nazywa się też sortowaniem przez prostą zamianę.

Specyfikacja problemu sortowania. Dane: liczba naturalna n i n-elementowa lista A liczb całkowitych. Wynik: lista A po uporządkowaniu, czyli A[0] ≤ A[1] ≤ … ≤ A[n-1].

Ciekawostka: sortowanie da się zatańczyć. Na kanale AlgoRythmics w serwisie YouTube węgierski zespół folkowy pokazuje algorytmy w tańcu, na przykład w filmie „Bubble-sort with Hungarian (Csángó) folk dance”.

Podręcznik Informatyka na czasie 2, s. 139–140 (9.4 Algorytmy sortowania, ramka „Specyfikacja”; 9.5 Sortowanie bąbelkowe, definicja i operacja prostej zamiany) · ciekawostka: ramka „A to ciekawe” ze s. 140, film sprawdzony pod adresem youtube.com/watch?v=lyZQPjUT5B4
Część 1 · Przykład krok po kroku

Pięć liczb, cztery etapy

Porządkujemy listę 6, 4, 9, 1, 5 niemalejąco, czyli tak, żeby każda kolejna liczba była większa od poprzedniej albo jej równa. Pierwszy etap ustawia największą liczbę na ostatniej pozycji. W drugim etapie pomijamy już ostatni element, w trzecim dwa ostatnie, w czwartym trzy.

Etap 1: cztery porównania 6 4 9 1 5 lista na starcie 4 6 9 1 5 6 > 4, zamiana 4 6 9 1 5 6 < 9, bez zamiany 4 6 1 9 5 9 > 1, zamiana 4 6 1 5 9 9 > 5, zamiana Największa liczba stoi na końcu Etapy 2, 3 i 4 Etap 2: 4 1 5 6 9 2 zamiany Etap 3: 1 4 5 6 9 1 zamiana Etap 4: 1 4 5 6 9 0 zamian Razem: 10 porównań i 6 zamian
Podręcznik Informatyka na czasie 2, s. 141 (9.5 Sortowanie bąbelkowe, algorytm na przykładzie listy 6, 4, 9, 1, 5)
Część 1 · Lista kroków i kod

Dwie pętle, jedna w drugiej

  1. Wczytaj listę liczb A.
  2. Dla wartości i równych kolejno 1, 2, …, n-1 powtarzaj kroki 3 oraz 4.
  3. Dla wartości j równych kolejno 0, 1, …, n-i-1 powtarzaj krok 4.
  4. Jeśli A[j] > A[j+1], to zamień te elementy miejscami.
1. def bubble_sort(A):
2.     n = len(A)
3.     for i in range(1, n):
4.         for j in range(0, n-i):
5.             if A[j] > A[j+1]:
6.                 A[j], A[j+1] = A[j+1], A[j]

Pętle zagnieżdżone (ang. nested loops) to pętle umieszczone wewnątrz innych pętli. Zewnętrzna liczy etapy i wykonuje się n-1 razy, wewnętrzna robi porównania w jednym etapie. Każdy etap ustawia jedną liczbę na docelowym miejscu, więc w następnym etapie porównań jest o jedno mniej.

Podręcznik Informatyka na czasie 2, s. 142 (9.5 Sortowanie bąbelkowe, pojęcie pętli zagnieżdżonych, lista kroków, kod źródłowy funkcji bubble_sort)
Część 1 · Zamiana miejscami

Jak zamienić dwie wartości?

Dwóch wartości nie da się zamienić wprost: jeśli od razu wpiszemy 4 do A[j], to szóstka przepadnie. Dlatego najpierw chowamy jedną z nich w zmiennej pomocniczej.

tmp 6 A[j] 6 A[j+1] 4 1 3 2 1. chowamy A[j] w tmp    2. A[j+1] wchodzi na miejsce A[j]    3. tmp wraca na A[j+1]

W linii 6. kodu Python robi to samo krócej: A[j], A[j+1] = A[j+1], A[j]. Po prawej stronie znaku równości powstaje krotka (ang. tuple), czyli odpowiednik listy, którego nie da się zmieniać. Python zapamiętuje w niej obie wartości i dopiero potem wpisuje je na zamienione miejsca. Rada z podręcznika: żeby porządkować nierosnąco, zmieńcie w warunku znak „>” na „<”.

Podręcznik Informatyka na czasie 2, s. 142 (9.5 Sortowanie bąbelkowe, opis linii 6. i pojęcie krotki, ramka „Dobra rada”) · w podręczniku jest tylko wersja z krotką
Część 2 · Sortowanie przez wstawianie

Jak układacie karty w ręku?

Sortowanie przez wstawianie (ang. insertion sort) przegląda kolejne elementy listy od lewej i przenosi je w odpowiednie miejsce uporządkowanego już fragmentu po lewej stronie. Dokładnie tak układa się karty do gry: kartę podniesioną ze stołu wsuwacie między te, które już macie ułożone.

Ta sama lista: 6, 4, 9, 1, 5 Etap 1: 4 6 9 1 5 temp = 4, przesuwamy 6 w prawo Etap 2: 4 6 9 1 5 temp = 9, nic nie przesuwamy Etap 3: 1 4 6 9 5 temp = 1, przesuwamy 9, 6 i 4 Etap 4: 1 4 5 6 9 temp = 5, przesuwamy 9 i 6 Zielona ramka: część listy już uporządkowana. Razem 6 przesunięć
Podręcznik Informatyka na czasie 2, s. 143–145 (9.6 Sortowanie przez wstawianie: definicja, rys. 9.12 układanie kart, etapy dla listy 6, 4, 9, 1, 5 ze s. 144, podział listy na część posortowaną i nieposortowaną)
Część 2 · Kod i porównanie

Funkcja insertion_sort

1. def insertion_sort(A):
2.     n = len(A)
3.     for i in range(1, n):
4.         temp = A[i]
5.         j = i - 1
6.         while j >= 0 and A[j] > temp:
7.             A[j+1] = A[j]
8.             j -= 1
9.         A[j+1] = temp
  • Linia 4.: w zmiennej temp chowamy liczbę, dla której szukamy miejsca.
  • Linia 6.: warunek ze słowem and to koniunkcja, oba warunki muszą być prawdziwe naraz.
  • Python sprawdza je po kolei i odpuszcza drugi, gdy pierwszy jest fałszywy. To leniwe wartościowanie.
  • Linia 8.: j -= 1 to krótszy zapis j = j - 1.

Oba algorytmy sortują w miejscu: nie budują drugiej listy na wynik.

Podręcznik Informatyka na czasie 2, s. 145–146 (9.6 Sortowanie przez wstawianie: lista kroków, kod źródłowy funkcji insertion_sort, koniunkcja i leniwe wartościowanie, ramki „Warto wiedzieć” o operacjach w miejscu i o szybkości)
Ćwiczenie · na kartce · 12 minut

Ćwiczenie: sortujesz ręcznie

  1. Podpisz kartkę. Uporządkuj niemalejąco listę A = [3, 0, 1, 7, 5, 2] sortowaniem bąbelkowym. Po każdym etapie zapisz stan listy oraz liczbę porównań i zamian, a na dole zsumuj obie kolumny.
  2. Dla listy C = [8, 2, 3, 5] wykonaj jeden etap sortowania przez wstawianie: co trafia do temp, co przesuwasz, jaka jest lista po etapie.
Etap | Lista po etapie | Por. | Zam.
  1  |                 |      |
  2  |                 |      |
  3  |                 |      |
  4  |                 |      |
  5  |                 |      |
Razem|                 |      |

Dla chętnych (dom): zapisz funkcję bubble_sort ze slajdu 5 w pliku sorting.py i uruchom ją na własnej liście.

Dla najszybszych: sortowanie przez wybór

Sortowanie przez wybór (ang. selection sort). Lista dzieli się na część uporządkowaną i nieuporządkowaną. W każdym etapie szukasz najmniejszej liczby w części nieuporządkowanej i zamieniasz ją miejscami z pierwszą liczbą tej części, a granica między częściami przesuwa się o jedno miejsce w prawo. Porównań jest tyle samo co w bąbelkowym, czyli n·(n-1)/2, ale zamian najwyżej n-1: jedna na etap. Dlatego ten algorytm wygrywa tam, gdzie zapis danych jest kosztowny. Opis mam z en.wikipedia.org/wiki/Selection_sort, podręcznik go nie omawia.

Podręcznik Informatyka na czasie 2, s. 142 (ćwiczenie 7), s. 145 (ćwiczenie 9) i s. 147 (zadanie 8)
Część 3 · Zamknięcie rozdziału

Gdzie to wróci po szkole?

To ostatnia lekcja rozdziału o algorytmice. Podręcznik zamyka go czterema scenariuszami zawodowymi.

Podręcznik Informatyka na czasie 2, s. 148 („Z informatyką w przyszłość”, Algorytmika i programowanie w języku Python, cztery scenariusze zawodowe)
Część 3 · Pytania kontrolne

Trzy pytania na koniec

  1. Na czym polega operacja prostej zamiany i dlaczego sortowanie bąbelkowe bierze od niej drugą nazwę?
  2. Skąd w funkcji bubble_sort biorą się dwie pętle, jedna w drugiej, i dlaczego wewnętrzna robi w każdym kolejnym etapie o jedno porównanie mniej?
  3. Po co sortowaniu przez wstawianie zmienna pomocnicza temp? Co stałoby się bez niej?
Podręcznik Informatyka na czasie 2, s. 140–146 (9.5 Sortowanie bąbelkowe, 9.6 Sortowanie przez wstawianie, ramki „Zapamiętaj”)
Część 3 · Podsumowanie

A jak to wygląda w produkcji?

Na lekcjiW produkcjiStatus
Sortowanie bąbelkowe pisane od zeraNikt nie pisze go po to, żeby uporządkować dane. Zostaje jako ćwiczenie na zrozumienie algorytmu.zastąpione
Własna funkcja sortującaW Pythonie sortuje gotowa funkcja sorted(), która oddaje nową listę, i metoda list.sort(), która działa w miejscu.narzędzia
Wybór jednego algorytmuPod spodem pracuje algorytm hybrydowy: dokumentacja Pythona nazywa go Timsort i pisze, że korzysta z porządku już obecnego w danych.rozszerzane
Sortowanie przez wstawianieWraca w rozwiązaniach hybrydowych: przy krótkich fragmentach listy jest szybkie, więc kończy nim sortowanie szybkie.nadal w użyciu
Porządkowanie listy liczbW sklepie internetowym to sortowanie wyników po cenie, a w bazie danych sortowanie wyniku kwerendy z rozdziału o bazach.nadal w użyciu
Wiersze o funkcjach sorted() i list.sort() oraz o algorytmie Timsort: dokumentacja Pythona, docs.python.org/3/howto/sorting.html (sprawdzone) · sortowanie przez wstawianie w ostatniej fazie sortowania szybkiego: podręcznik s. 146 (ramka „Warto wiedzieć”)