Menu
Coddy logo textTech

Merge sort (sortowanie przez scalanie)

Ostatnia aktualizacja

Merge sort to algorytm typu dziel i zwyciężaj. Rekurencyjnie dzieli tablicę na pół, aż każdy fragment ma jeden element (który jest trywialnie posortowany), a potem scala fragmenty z powrotem we właściwej kolejności. Krok scalania przechodzi dwie posortowane podtablice dwoma wskaźnikami i zawsze kopiuje jako następny mniejszy z elementów na ich początku. Kliknij odtwarzanie powyżej i zobacz, jak tablica jest odbudowywana scalanie po scalaniu.

Ponieważ zawsze dzieli dane na pół, merge sort działa w czasie O(n log n) w każdym przypadku: najgorszy przypadek jest tak samo dobry jak najlepszy. Kosztem jest O(n) dodatkowej pamięci na tymczasowy bufor scalania.

Złożoność czasowa i pamięciowa

PrzypadekZłożonośćUwagi
Najlepszy przypadekO(n log n)Zawsze dzieli dane na pół
Średni przypadekO(n log n)Losowa kolejność
Najgorszy przypadekO(n log n)Gwarantowany: brak złych danych wejściowych
PamięćO(n)Tymczasowy bufor do scalania
StabilneTakPrzy remisach scalanie bierze najpierw z lewej

Krok po kroku

KrokCo się dzieje
1Jeśli zakres ma 0 lub 1 element, jest już posortowany.
2Podziel zakres na dwie połowy.
3Rekurencyjnie posortuj lewą połowę przez scalanie.
4Rekurencyjnie posortuj prawą połowę przez scalanie.
5Scal dwie posortowane połowy za pomocą dwóch wskaźników.

Przykład krok po kroku

Sortowanie [5, 2, 4, 1]:

PrzebiegTablicaDziałanie
Podział[5, 2] | [4, 1]Podziel tablicę na dwie połowy
Podział[5] [2] | [4] [1]Dziel dalej, aż każdy fragment będzie jednym elementem
Scalanie[2, 5] | [1, 4]Scal [5],[2] w [2, 5] oraz [4],[1] w [1, 4]
Scalanie[1, 2, 4, 5]Scal [2, 5] i [1, 4]: wybierz 1, potem 2, potem 4, potem 5
Koniec[1, 2, 4, 5]Tablica jest w pełni posortowana

Kiedy używać sortowania przez scalanie

Używaj, gdyUnikaj, gdy
Potrzebujesz gwarantowanego O(n log n) w najgorszym przypadkuPamięci jest mało i O(n) dodatkowej pamięci jest nie do przyjęcia
Liczy się stabilność (równe klucze zachowują kolejność)Sortujesz małe tablice, dla których sortowanie przez wstawianie jest szybsze
Sortujesz listę jednokierunkowąSortowanie w miejscu jest twardym wymaganiem
Dane są za duże, by zmieścić się w RAM (sortowanie zewnętrzne)Dominuje lokalność pamięci podręcznej i wygrywają przebiegi quicksorta w miejscu

Merge Sort: kod

Przejrzysta, gotowa do uruchomienia implementacja algorytmu Merge Sort w językach: Python, JavaScript, Java, C++, C, Pseudocode. Wybierz język, skopiuj kod albo otwórz go od razu w edytorze online Coddy.

Merge Sort: kod (Python)

Python
1def merge_sort(a):2    if len(a) <= 1:3        return a4    mid = len(a) // 25    left = merge_sort(a[:mid])6    right = merge_sort(a[mid:])7    return merge(left, right)8
9
10def merge(left, right):11    out = []12    i = j = 013    while i < len(left) and j < len(right):14        if left[i] <= right[j]:15            out.append(left[i])16            i += 117        else:18            out.append(right[j])19            j += 120    out.extend(left[i:])21    out.extend(right[j:])22    return out23
24
25nums = [38, 27, 43, 3, 9, 82, 10]26print("Before:", nums)27print("After: ", merge_sort(nums))
Uruchom ten kod w edytorze Python online

Merge sort: najczęstsze pytania

Jaka jest złożoność czasowa sortowania przez scalanie?
Merge sort ma złożoność O(n log n) w najlepszym, średnim i najgorszym przypadku, bo zawsze dzieli tablicę na pół. Zużywa O(n) dodatkowej pamięci na bufor scalania.
Czy sortowanie przez scalanie jest stabilne?
Tak, jeśli krok scalania przy remisach bierze najpierw element z lewej połowy. Dzięki temu równe elementy zachowują pierwotną względną kolejność, dlatego merge sort jest popularnym wyborem do stabilnego sortowania.
Dlaczego wybrać merge sort zamiast quicksorta?
Merge sort gwarantuje O(n log n) nawet dla złośliwych danych i jest stabilny, a quicksort może zdegradować się do O(n²). Merge sort jest też preferowany dla list jednokierunkowych i sortowania zewnętrznego. Wadą jest O(n) dodatkowej pamięci.
Czym różni się merge sort od quicksorta?
Oba są algorytmami typu dziel i zwyciężaj, ale quicksort dzieli dane wokół pivota i sortuje w miejscu z O(log n) pamięci na stos, a merge sort dzieli na ślepo na pół i scala z użyciem bufora O(n). Quicksort jest w praktyce zwykle szybszy dzięki lokalności pamięci podręcznej, ale merge sort ma gwarantowane O(n log n) w najgorszym przypadku i jest stabilny.
Kiedy w praktyce używać sortowania przez scalanie?
Sięgnij po merge sort, gdy potrzebujesz stabilnego sortowania z gwarantowanym ograniczeniem O(n log n), gdy sortujesz listy jednokierunkowe (gdzie nie jest potrzebny dostęp swobodny) albo gdy wykonujesz sortowanie zewnętrzne danych zbyt dużych, by zmieściły się w pamięci. Unikaj go, gdy pamięci brakuje, bo potrzebuje O(n) dodatkowej przestrzeni.
Czy merge sort sortuje w miejscu?
Nie. Standardowy merge sort alokuje tymczasowy bufor O(n) do scalania dwóch połówek, więc nie działa w miejscu. Istnieją warianty scalania w miejscu, ale są złożone i albo wolniejsze, albo tracą stabilność, dlatego zwykle wybiera się wersję z buforem.
Ilustracja języków programowania w Coddy

Opanuj algorytmy z Coddy

ZACZNIJ