średniAlgorytmyPythonC++

Sortowanie Bąbelkowe (Bubble Sort) na Maturze z Informatyki

15 min czytania
Python, C++
Zaktualizowano: 3.11.2025

Sortowanie bąbelkowe to jeden z najprostszych algorytmów sortowania, jaki poznasz. Jego nazwa wzięła się z analogii do bąbelków powietrza w wodzie – elementy 'lżejsze' (mniejsze liczby) stopniowo 'wypływają' na początek tablicy, a 'cięższe' (większe liczby) 'toną' na jej koniec. Algorytm ten działa poprzez wielokrotne przechodzenie przez tablicę, porównywanie sąsiednich elementów i zamienianie ich miejscami, jeśli są w złej kolejności. Jest to świetny algorytm do nauki podstaw sortowania, ponieważ jego logika jest bardzo intuicyjna. Chociaż jest prosty do zrozumienia i zaimplementowania, rzadko jest najlepszym wyborem w praktyce z powodu swojej niskiej wydajności dla dużych zbiorów danych.

Dlaczego to ważne? Na maturze sortowanie bąbelkowe jest ważne z dwóch powodów. Po pierwsze, jest tak proste, że możesz je napisać z pamięci w 3 minuty, jeśli będziesz potrzebować *jakiegokolwiek* działającego sortowania dla małego zbioru danych. Po drugie, CKE lubi pytać o algorytmy o złożoności kwadratowej (O(n^2)) w zadaniach teoretycznych, np. o śledzenie liczby zamian lub porównań. Musisz je rozumieć, nawet jeśli w praktyce będziesz używać wbudowanej funkcji `.sort()`.

Teoria

Główna idea polega na wielokrotnym przechodzeniu przez tablicę i porównywaniu par sąsiednich elementów (`tab[j]` i `tab[j+1]`). Jeśli elementy są w złej kolejności (np. `tab[j] > tab[j+1]` przy sortowaniu rosnącym), zamieniamy je miejscami. Powtarzamy ten proces (przejście) tyle razy, aż tablica będzie posortowana.

Jak to działa?

  1. Krok 1: Rozpocznij pętlę zewnętrzną 'i', która wykona się n-1 razy (gdzie 'n' to liczba elementów). Ta pętla odpowiada za liczbę 'przejść' przez tablicę.
  2. Krok 2: Wewnątrz pętli 'i', uruchom pętlę wewnętrzną 'j', która będzie przechodzić od początku tablicy do `n-i-1`.
  3. Krok 3: (Optymalizacja `n-i-1`): Po każdym przejściu 'i', największy element z niesortowanej części 'ląduje' na końcu. Nie musimy więc już sprawdzać posortowanego 'ogona' tablicy.
  4. Krok 4: W pętli 'j', porównaj `tab[j]` z `tab[j+1]`.
  5. Krok 5: Jeśli `tab[j] > tab[j+1]`, zamień je miejscami (operacja 'swap').
  6. Krok 6: Po zakończeniu obu pętli, tablica jest posortowana.

Złożoność: Złożoność czasowa: O(n²) (kwadratowa). W najgorszym (i średnim) przypadku musimy wykonać mniej więcej n*n porównań. Dzieje się tak z powodu dwóch zagnieżdżonych pętli, z których każda jest zależna od 'n'. To sprawia, że algorytm jest bardzo wolny dla dużych 'n' (np. n > 10 000). Złożoność pamięciowa: O(1) (stała), ponieważ sortujemy tablicę 'w miejscu' (in-place) i potrzebujemy co najwyżej jednej dodatkowej zmiennej do zamiany.

Implementacja

Standardowe sortowanie bąbelkowe

Python
def bubble_sort(tab):
    n = len(tab)
    
    # Pętla zewnętrzna (przejścia)
    for i in range(n - 1):
        # Pętla wewnętrzna (porównania)
        # Optymalizacja: n-i-1, bo po i-tym przejściu
        # i-elementów na końcu jest już posortowanych
        for j in range(0, n - i - 1):
            # Porównanie sąsiadów
            if tab[j] > tab[j + 1]:
                # Zamiana miejscami
                tab[j], tab[j + 1] = tab[j + 1], tab[j]
    return tab

dane = [64, 34, 25, 12, 22, 11, 90]
print(f"Przed: {dane}")
bubble_sort(dane)
print(f"Po: {dane}")

To jest klasyczna, zoptymalizowana implementacja. `n = len(tab)`. Pętla zewnętrzna `i` idzie od 0 do `n-2`. Pętla wewnętrzna `j` idzie od 0 do `n-i-2`. W Pythonie zamiana `tab[j], tab[j+1] = tab[j+1], tab[j]` jest bardzo wygodna.

Wersja zoptymalizowana (z flagą 'swapped')

Python
def bubble_sort_opt(tab):
    n = len(tab)
    for i in range(n - 1):
        swapped = False # Flaga sprawdzająca zamiany
        for j in range(0, n - i - 1):
            if tab[j] > tab[j + 1]:
                tab[j], tab[j + 1] = tab[j + 1], tab[j]
                swapped = True
        
        # Jeśli w całym przejściu nie było ani jednej zamiany,
        # to tablica jest już posortowana. Możemy przerwać.
        if not swapped:
            break
    return tab

dane = [1, 2, 3, 5, 4, 6]
print(bubble_sort_opt(dane))

To jest ulepszona wersja. Dodajemy flagę `swapped`. Jeśli wewnętrzna pętla przejdzie całą tablicę i nie dokona *ani jednej* zamiany, oznacza to, że tablica jest już posortowana. Wtedy `break` przerywa pętlę zewnętrzną. To znacznie przyspiesza algorytm dla danych częściowo posortowanych.

Standardowe sortowanie bąbelkowe (vector)

C++
#include <iostream>
#include <vector>
#include <algorithm> // dla std::swap

using namespace std;

void bubble_sort(vector<int>& tab) {
    int n = tab.size();
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (tab[j] > tab[j + 1]) {
                // Używamy std::swap do zamiany
                swap(tab[j], tab[j + 1]);
            }
        }
    }
}

int main() {
    vector<int> dane = {64, 34, 25, 12, 22, 11, 90};
    bubble_sort(dane);
    for (int x : dane) {
        cout << x << " ";
    }
    cout << endl;
    return 0;
}

Logika jest identyczna jak w Pythonie. Używamy `vector` jako naszej tablicy. Do zamiany elementów najwygodniej użyć funkcji `swap(a, b)` z biblioteki `<algorithm>`. Zamiast `vector` można też użyć statycznej tablicy `int dane[]`, ale `vector` jest bardziej elastyczny.

Przykładowe Zadania Maturalne

Matura 2026Zadanie Zadanie Typu Maturalnego 1

W pliku 'dane.txt' znajduje się 100 liczb całkowitych, każda w osobnym wierszu. Wczytaj wszystkie liczby do tablicy. Następnie posortuj tę tablicę rosnąco, implementując algorytm sortowania bąbelkowego. Na koniec wypisz 10 najmniejszych liczb z posortowanej tablicy.

Wskazówka: Najpierw wczytaj wszystkie 100 liczb do listy (tablicy). Następnie przekaż tę listę do swojej funkcji `bubble_sort()`. Po posortowaniu, 10 najmniejszych liczb to będzie po prostu 10 *pierwszych* elementów tablicy (o indeksach od 0 do 9).

Pokaż szkic rozwiązania
1. Stwórz pustą listę `liczby = []`.
2. Otwórz plik 'dane.txt' do odczytu.
3. W pętli `for linia in plik:`:
   a. `liczby.append(int(linia.strip()))`.
4. Zaimplementuj funkcję `bubble_sort(tab)` (jak w przykładzie kodu).
5. Wywołaj sortowanie na wczytanych danych: `bubble_sort(liczby)`.
6. Po posortowaniu, wypisz 10 pierwszych elementów:
   a. `for i in range(10):`
   b. `  print(liczby[i])`.
Matura 2023Zadanie 2.3 (Matura Czerwiec 2023)

Dana jest dodatnia liczba całkowita n oraz słowo s[1..n]. Naszym celem jest obliczenie wartości elementów tablicy T[1..n] zawierającej numery sufiksów słowa s[1..n] uporządkowanych w porządku alfabetycznym. Zapisz w wybranej przez siebie notacji algorytm, który obliczy wartości elementów tablicy T. Możesz wykorzystać funkcję `czy_mniejszy(n, s, k1, k2)` podaną w arkuszu.

Wskazówka: To zadanie wprost prosi o algorytm sortujący. Twoim zadaniem jest posortowanie tablicy indeksów `T = [1, 2, 3, ..., n]`. Użyj sortowania bąbelkowego, ale zamiast porównywać `T[j] > T[j+1]`, musisz użyć podanej funkcji `czy_mniejszy(n, s, T[j+1], T[j])`, aby sprawdzić, czy sufiks o indeksie `T[j+1]` jest alfabetycznie mniejszy niż sufiks o indeksie `T[j]`.

Pokaż szkic rozwiązania
1. Wczytaj `n` oraz słowo `s`.
2. Stwórz tablicę `T` wypełnioną liczbami od 1 do n (np. w Pythonie `T = list(range(1, n + 1))`).
3. Zaimplementuj funkcję `czy_mniejszy(n, s, k1, k2)` (zgodnie z treścią zadania).
4. Zastosuj sortowanie bąbelkowe na tablicy `T`:
   a. `for i in range(n - 1):`
   b. `  for j in range(n - i - 1):`
   c. `    # Sprawdź, czy T[j+1] jest mniejszy niż T[j]`
   d. `    if czy_mniejszy(n, s, T[j + 1], T[j]):`
   e. `      # Zamień elementy w tablicy T`
   f. `      T[j], T[j + 1] = T[j + 1], T[j]`
5. Po zakończeniu pętli tablica `T` zawiera posortowane indeksy sufiksów.

Częste Błędy

Używanie Bubble Sort dla dużych danych

Sortowanie bąbelkowe ma złożoność O(n^2). Dla n=3000 (jak w niektórych zadaniach) daje to 9,000,000 operacji, co jest na granicy limitu czasu. Dla n=100,000 (10 miliardów operacji) na pewno przekroczy limit czasu.

Poprawka: Jeśli masz posortować duży zbiór (n > ok. 5000) i *nie ma* wymogu implementacji algorytmu, *zawsze* używaj wbudowanej funkcji `list.sort()` (w Pythonie) lub `std::sort()` (w C++). Działają one w czasie O(n log n).

Błąd 'Off-by-One' w pętlach

Bardzo częsty błąd. Pętla zewnętrzna powinna iść `n-1` razy (`range(n-1)`). Pętla wewnętrzna musi się skracać (`range(n-i-1)`), a wewnątrz niej odwołujemy się do `j` oraz `j+1`. Łatwo tu wyjść poza zakres tablicy.

Poprawka: Zapamiętaj wzorzec: `for i in range(n-1):` i `for j in range(n-i-1):`. To najbezpieczniejsza kombinacja.

Błędna implementacja zamiany (swap)

W C++ pomyłka typu: `temp = a; a = b; b = a;` (zamiast `b = temp`). W Pythonie błąd jest rzadszy, ale możliwy.

Poprawka: W C++ trzymaj się schematu: `temp = a; a = b; b = temp;` lub użyj `swap(a, b)`. W Pythonie używaj `a, b = b, a`.

Sortowanie rosnąco zamiast malejąco (i na odwrót)

Zadanie prosi o sortowanie malejąco, a ty piszesz `if tab[j] > tab[j+1]`. To sortuje rosnąco.

Poprawka: Aby sortować rosnąco, zamieniaj gdy `tab[j] > tab[j+1]`. Aby sortować malejąco, zamieniaj gdy `tab[j] < tab[j+1]`.

Kluczowe Wnioski

  • Sortowanie bąbelkowe to prosty, ale wolny algorytm sortowania o złożoności O(n^2).
  • Jego główna idea to porównywanie i zamienianie *sąsiednich* elementów (`tab[j]` i `tab[j+1]`).
  • Posiada dwie zagnieżdżone pętle FOR.
  • Jest to algorytm 'stabilny' i 'w miejscu' (O(1) pamięci).
  • Na maturze używaj wbudowanego `.sort()` (O(n log n)), *chyba że* zadanie każe zaimplementować własny algorytm lub dane są bardzo małe.
  • Wersja zoptymalizowana z flagą `swapped` przerywa sortowanie, gdy tablica jest już uporządkowana (najlepszy przypadek O(n)).

Najczęściej Zadawane Pytania

Czy mogę użyć wbudowanej funkcji .sort() na maturze?

Tak! Jest to nawet zalecane. Używaj `nazwa_listy.sort()` (w Pythonie) lub `sort(nazwa_wektora.begin(), nazwa_wektora.end())` (w C++) zawsze, gdy zadanie polega na sortowaniu, ale nie wymaga implementacji *konkretnego* algorytmu (jak bubble sort).

Dlaczego złożoność bubble sort to O(n^2)?

Wyobraź sobie tablicę 100-elementową. Pętla zewnętrzna wykona się ok. 100 razy. Dla każdego z tych 100 przejść, pętla wewnętrzna wykona się (średnio) ok. 50 razy. To daje 100 * 50 = 5000 operacji. Dla n, jest to (n-1) * (n/2) operacji, co po uproszczeniu daje O(n^2).

Dlaczego pętla wewnętrzna jest do `n-i-1`?

To optymalizacja. Po pierwszym przejściu (i=0), największy element jest na 100% na ostatnim miejscu (`n-1`). Po drugim przejściu (i=1), dwa największe są na miejscach `n-2` i `n-1`. Nie ma sensu ich ponownie sprawdzać. Ta optymalizacja skraca pętlę wewnętrzną o 1 w każdej iteracji zewnętrznej.

Czy sortowanie bąbelkowe jest 'stabilne'?

Tak. 'Stabilne' sortowanie oznacza, że elementy o tej samej wartości zachowują swoją pierwotną kolejność. Ponieważ sortowanie bąbelkowe zamienia elementy tylko wtedy, gdy `tab[j] > tab[j+1]`, dwa równe elementy (`tab[j] == tab[j+1]`) nigdy nie zostaną zamienione.

Chcesz opanować wszystkie tematy maturalne?

Dołącz do kursu i zyskaj dostęp do interaktywnych lekcji, edytora kodu i setek zadań.

Powiązane Tematy