Sortowanie bąbelkowe, zwane również bubble sort, to jeden z najprostszych algorytmów sortowania. Choć algorytm nie jest wydajny dla dużych zestawów danych, jego prostota sprawia, że jest popularnym wyborem na początek nauki algorytmów sortowania.
Sortowanie bąbelkowe działa poprzez wielokrotne porównywanie sąsiadujących elementów w liście danych. Pozwala na uporządkowanie wartości rosnąco lub malejąco.
W każdym cyklu algorytmu każde kolejne dwie liczby są porównywane ze sobą i zamieniane miejscami, jeśli są w niewłaściwej kolejności. Proces powtarza się aż do pełnego posortowania danych. Algorytm, choć prosty, nie jest optymalnym wyborem do sortowania dużych zbiorów danych ze względu na niską efektywność przy większej liczbie elementów. Jednak często wykorzystuje się go w czasie nauki jako wprowadzenie do poznania metod sortowania.
Poniżej znajdziesz przykład sortowania listy 4, 2, 1, 7, 5 w formie grafiki GIF oraz zapisu tekstowego. Liczby są sortowane od lewej do prawej w kolejności rosnącej.

Pod spodem umieszczono przykład użycia sortowania bąbelkowego w formie zapisu tekstowego. Zapoznaj się z nim dla lepszego zrozumienia zasady jego działania.
| Sortowane liczby | Komentarz |
| 4 2 1 7 5 | Początkowy układ liczb. |
| 4 2 1 7 5 | Czerwone liczby to te, które aktualnie rozpatrujemy. Z kolei nawiasy oznaczają wartości, które są ze sobą porównywane. Rozpoczynamy sortowanie od lewej strony, czyli od liczby 4. |
| (4 2) 1 7 5 | Porównujemy 4 i 2. Wartość 4 jest większa, więc następuje zamiana. |
| 2 4 1 7 5 | - |
| 2 (4 1) 7 5 | Porównujemy 4 i 1. Liczba 4 jest większa, więc również następuje zamiana. |
| 2 1 4 7 5 | - |
| 2 1 (4 7) 5 | Następuje porównanie 4 i 7. Jednak w tym przypadku 4 jest mniejsze, więc nie ma zamiany. |
| 2 1 4 7 5 | - |
| 2 1 4 (7 5) | Porównujemy 7 i 5. Wartość 7 jest większa, zatem wykonujemy zamianę. |
| 2 1 4 5 7 | - |
| 2 1 4 5 7 | W tym momencie pojedynczy cykl sortowania (iteracja) został zakończony i następuje kolejna iteracja, która również rozpoczyna się od lewej. |
| (2 1) 4 5 7 | Porównujemy 2 i 1. Liczba 2 jest większa, więc następuje zamiana. |
| 1 2 4 5 7 | - |
| 1 (2 4) 5 7 | Porównujemy 2 i 4. Wartość 2 jest mniejsza, więc zamiana nie występuje. |
| 1 2 4 5 7 | - |
| 1 2 (4 5) 7 | Porównujemy 4 i 5. Liczba 4 jest mniejsza, czyli nie następuje zamiana. |
| 1 2 4 5 7 | - |
| 1 2 4 (5 7) | Porównujemy 5 i 7. Jednak liczba 5 jest mniejsza, więc nie ma zamiany. |
| 1 2 4 5 7 | Tutaj zakończył się kolejny cykl sortowania, drugi z pięciu. Co prawda w tym przypadku tablica jest już posortowana, jednak w podstawowej wersji algorytmu nadal sortuje on listę, dopóki nie minie z góry ustalona liczba iteracji (w tym przypadku 5, tyle ile jest liczb w tablicy). |
| 1 2 4 5 7 | Rozpoczyna się kolejna iteracja. |
| (1 2) 4 5 7 | - |
| 1 2 4 5 7 | - |
| 1 (2 4) 5 7 | - |
| 1 2 4 5 7 | - |
| 1 2 (4 5) 7 | - |
| 1 2 4 5 7 | - |
| 1 2 4 (5 7) | - |
| 1 2 4 5 7 | Trzecia iteracja została zakończona. Jak widać, miejsce żadnej z liczb nie uległo zamianie. Kolejne dwa cykle sortowania wyglądałyby identycznie, dlatego zostaną w tym przypadku pominięte. |

funkcja sortowanie_babelkowe (tab, n)
dla i = 1, 2, …, n wykonuj
dla j = 1, 2, …, n wykonuj
jeżeli tab [j] > tab [j+1]
pom ← tab [j]
tab [j] ← tab [j+1]
tab [j+1] ← pom
zwróć tabKomentarze do pseudokodu sortowania bąbelkowego
tab = [5, 3, 8, 2, 1, 7]
# Algorytm sortowania babelkowego
n = len(tab)
for i in range(n):
for j in range(n - 1):
if tab[j] > tab[j + 1]:
pom = tab[j]
tab[j] = tab[j + 1]
tab[j + 1] = pom
# Wypisanie posortowanej listy
for element in tab:
print(element, end=" ")#include <iostream>
using namespace std;
int main() {
int tab[] = {5, 3, 8, 2, 1, 7};
int n = sizeof(tab) / sizeof(tab[0]); // automatyczne wskazanie ilosci elementow danej tablicy
// Algorytm sortowania babelkowego
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1; j++) {
if (tab[j] > tab[j+1]) {
int pom = tab[j];
tab[j] = tab[j+1];
tab[j+1] = pom;
}
}
}
// Wypisanie posortowanej tablicy
for (int i = 0; i < n; i++) {
cout << tab[i] << " ";
}
return 0;
}public class Main {
public static void main(String[] args) {
int[] tab = {5, 3, 8, 2, 1, 7};
// Algorytm sortowania babelkowego
for (int i = 0; i < tab.length - 1; i++) {
for (int j = 0; j < tab.length - 1; j++) {
if (tab[j] > tab[j+1]) {
int pom = tab[j];
tab[j] = tab[j+1];
tab[j+1] = pom;
}
}
}
// Wypisanie posortowanej tablicy
for (int element : tab) {
System.out.print(element + " ");
}
}
}
funkcja zoptymalizowane_sortowanie_babelkowe (tab, n)
dla i = 1, 2, … n - 1 wykonuj
dla j = 1, 2, … n - i - 1 wykonuj
jeżeli tab [j] > tab [j+1]
pom ← tab [j]
tab [j] ← tab [j+1]
tab [j+1] ← pom
zwróć tabKomentarze do pseudokodu zoptymalizowanego sortowania bąbelkowego
Do implementacji zoptymalizowanego algorytmu konieczne jest użycie zagnieżdżonych pętli for. Pętla zewnętrzna powinna wykonywać się n - 1 razy, gdzie n to liczba elementów w sortowanym zbiorze.
Z kolei “- 1” stosowane jest, bo ostatni cykl byłby wykonywany na posortowanej tablicy/liście, co jest niepotrzebne, można więc ten krok pominąć. Natomiast druga pętla powinna działać do n - i - 1 iteracji, gdzie zmienna i jest wartością zmienianą przez zewnętrzną pętlę for.
Zapis n - i - 1 sprawia, że posortowane elementy znajdujące się na końcu listy nie są uwzględniane w kolejnych przebiegach. To istotne, bo te elementy są już prawidłowo porozmieszczane i nie ma potrzeby ponownego ich sprawdzania. Jeśli element o indeksie j jest większy od tego o indeksie j + 1, nastąpi zamiana miejscami.
tab = [5, 3, 8, 2, 1, 7]
# Kod algorytmu zoptymalizowanego sortowania bąbelkowego
n = len(tab)
for i in range(n - 1):
for j in range(n - i - 1):
if tab[j] > tab[j + 1]:
pom = tab[j]
tab[j] = tab[j + 1]
tab[j + 1] = pom
# Wypisanie posortowanej listy
for element in tab:
print(element, end=" ")
#include <iostream>
using namespace std;
int main() {
int tab[] = {5, 3, 8, 2, 1, 7};
int n = sizeof(tab) / sizeof(tab[0]); // automatyczne wskazanie ilosci elementow danej tablicy
// Kod algorytmu zoptymalizowanego sortowania babelkowego
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - i - 1; j++) {
if (tab[j] > tab[j+1]) {
int pom = tab[j];
tab[j] = tab[j+1];
tab[j+1] = pom;
}
}
}
// Wypisanie posortowanej tablicy
for (int i = 0; i < n; i++) {
cout << tab[i] << " ";
}
return 0;
}public class Main {
public static void main(String[] args) {
int[] tab = {5, 3, 8, 2, 1, 7};
// Kod algorytmu zoptymalizowanego sortowania babelkowego
for (int i = 0; i < tab.length - 1; i++) {
for (int j = 0; j < tab.length - i - 1; j++) {
if (tab[j] > tab[j+1]) {
int pom = tab[j];
tab[j] = tab[j+1];
tab[j+1] = pom;
}
}
}
// Wypisanie posortowanej tablicy
for (int element : tab) {
System.out.print(element + " ");
}
}
}Złożoność pamięciowa sortowania bąbelkowego to O(1).
Złożoność czasowa sortowania bąbelkowego to O(n²), jeśli chodzi o wersję podstawową (bez dołączonych optymalizacji).
Algorytm sortowania bąbelkowego cechuje się niską wydajnością przy większych zbiorach danych. Przechodzi przez cały zestaw, porównując kolejne pary sąsiadujących elementów, a po zakończeniu procesu rozpoczyna nową iterację. W najbardziej niekorzystnym przypadku (sytuacja pesymistyczna) elementy są posortowane odwrotnie do wymaganego przez algorytm porządku (czy to rosnącego, czy malejącego). Ta sytuacja dotyczy jednak jedynie zoptymalizowanej wersji algorytmu, ponieważ podstawowa wersja zawsze wykonuje tę samą liczbę operacji, niezależnie od początkowego układu danych.
Oprócz wcześniej przedstawionego podejścia jedną z najprostszych metod optymalizacji tego algorytmu jest wprowadzenie specjalnej flagi, która sygnalizuje, czy w danej iteracji zaszły jakiekolwiek zmiany. Jeżeli w trakcie cyklu sortowania nie doszło do przestawienia żadnego elementu, oznacza to, że zbiór danych jest już odpowiednio posortowany (czy to rosnąco, czy malejąco) i można przerwać dalsze działanie algorytmu. Choć taka zmiana nieco wydłuża czas trwania pojedynczej pętli, może znacząco ograniczyć liczbę niepotrzebnych iteracji, szczególnie w przypadku większych zbiorów danych.
Tak, sortowanie bąbelkowe sortuje w miejscu. Oznacza to, że do wykonania algorytmu nie jest potrzebna dodatkowa pamięć na przechowywanie elementów (poza drobnymi zmiennymi tymczasowymi), a sortowanie odbywa się bez tworzenia nowej tablicy – wszystkie operacje zamiany elementów zachodzą bezpośrednio w oryginalnej tablicy lub liście.
Złożoność czasowa sortowania bąbelkowego wynosi O(n²). W ramach sortowania bąbelkowego korzysta się z dwóch pętli, gdzie jedna jest zewnętrzna, a druga wewnętrzna względem zewnętrznej. Każda z nich jest wykonywana n razy, przez co mnoży się n * n, co można zapisać jako n². Dzięki temu wiadomo, że złożoność czasowa wynosi O(n²).