Menu
Coddy logo textTech

Heap sort (sortowanie przez kopcowanie)

Ostatnia aktualizacja

Sortowanie przez kopcowanie traktuje tablicę jak kopiec binarny. Najpierw buduje kopiec max, więc największy element trafia do korzenia (indeks 0). Potem wielokrotnie zamienia korzeń z ostatnim nieposortowanym elementem, co ustala maksimum na jego miejscu, i przesiewa nowy korzeń w dół, aby przywrócić własność kopca. Kliknij odtwarzanie powyżej i zobacz budowę kopca i kolejne wyciągnięcia.

Heap sort gwarantuje czas O(n log n) jak merge sort, ale sortuje w miejscu, zużywając tylko O(1) dodatkowej pamięci. Nie jest stabilny i zwykle gorzej współpracuje z pamięcią podręczną niż quicksort, dlatego wybiera się go często wtedy, gdy liczą się zarówno gwarantowane ograniczenie, jak i stała pamięć.

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

PrzypadekZłożonośćUwagi
Najlepszy przypadekO(n log n)Budowa + n wyciągnięć
Średni przypadekO(n log n)Losowa kolejność
Najgorszy przypadekO(n log n)Gwarantowany
PamięćO(1)W miejscu
StabilneNiePrzesiewanie w dół zmienia kolejność równych elementów

Krok po kroku

KrokCo się dzieje
1Zbuduj kopiec max z tablicy (przesiewając w dół od ostatniego rodzica).
2Zamień korzeń (maksimum) z ostatnim elementem kopca.
3Zmniejsz kopiec o jeden: ostatnie pole jest już posortowane.
4Przesiej nowy korzeń w dół, aby przywrócić własność kopca max.
5Powtarzaj, aż w kopcu zostanie jeden element.

Przykład krok po kroku

Sortowanie [3, 1, 6, 5, 2, 4]. Kreska | oznacza granicę między kurczącym się kopcem a posortowanym ogonem:

PrzebiegTablicaDziałanie
Budowa kopca[6, 5, 4, 1, 2, 3]Przesiewaj w dół od ostatniego rodzica, aby zbudować kopiec max; 6 jest teraz w korzeniu.
1[5, 3, 4, 1, 2 | 6]Zamień korzeń 6 z ostatnim polem, zmniejsz kopiec i przesiej 3 w dół.
2[4, 3, 2, 1 | 5, 6]Wyjmij korzeń 5, potem przesiej 2 w dół, aby 4 awansowało do korzenia.
3[3, 1, 2 | 4, 5, 6]Wyjmij korzeń 4, potem przesiej 1 w dół, aby 3 awansowało do korzenia.
4[2, 1 | 3, 4, 5, 6]Wyjmij korzeń 3; 2 już spełnia własność kopca.
5[1 | 2, 3, 4, 5, 6]Wyjmij korzeń 2; został jeden element, więc tablica jest posortowana.

Kiedy używać sortowania przez kopcowanie

Używaj, gdyUnikaj, gdy
Potrzebujesz gwarantowanego O(n log n) w najgorszym przypadku, bez ryzyka O(n²).Potrzebujesz stabilnego sortowania, które zachowuje kolejność równych kluczy.
Pamięci jest mało: sortuje w miejscu, zużywając tylko O(1) dodatkowej pamięci.Liczy się wydajność pamięci podręcznej, a dane mieszczą się w pamięci: quicksort jest zwykle szybszy.
Już utrzymujesz kopiec (np. kolejkę priorytetową) na tych danych.Chcesz jak najmniej porównań: merge sort i quicksort w praktyce często wykonują ich mniej.
Niezaufane dane wejściowe mogłyby wywołać najgorszy przypadek quicksorta, a nie możesz losować.Dane są prawie posortowane: sortowanie przez wstawianie działa na nich w czasie bliskim liniowemu.

Heap Sort: kod

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

Heap Sort: kod (Python)

Python
1def heap_sort(a):2    n = len(a)3    # Build a max-heap, deepest parent first4    for i in range(n // 2 - 1, -1, -1):5        sift_down(a, i, n)6    # Repeatedly move the max to the end and shrink the heap7    for end in range(n - 1, 0, -1):8        a[0], a[end] = a[end], a[0]9        sift_down(a, 0, end)10    return a11
12
13def sift_down(a, i, size):14    while True:15        largest = i16        left, right = 2 * i + 1, 2 * i + 217        if left < size and a[left] > a[largest]:18            largest = left19        if right < size and a[right] > a[largest]:20            largest = right21        if largest == i:22            return23        a[i], a[largest] = a[largest], a[i]24        i = largest25
26
27nums = [12, 11, 13, 5, 6, 7]28print("Before:", nums)29heap_sort(nums)30print("After: ", nums)
Uruchom ten kod w edytorze Python online

Heap sort: najczęstsze pytania

Jaka jest złożoność czasowa sortowania przez kopcowanie?
Heap sort ma złożoność O(n log n) w najlepszym, średnim i najgorszym przypadku. Budowa kopca kosztuje O(n), a każde z n wyciągnięć kosztuje O(log n). Zużywa O(1) dodatkowej pamięci.
Czy sortowanie przez kopcowanie jest stabilne?
Nie. Operacja przesiewania w dół może przestawić równe elementy względem siebie, więc heap sort nie zachowuje względnej kolejności równych kluczy.
Kiedy używać sortowania przez kopcowanie?
Używaj heap sort, gdy potrzebujesz gwarantowanego O(n log n) w najgorszym przypadku przy zaledwie O(1) dodatkowej pamięci. Unika ryzyka O(n²) quicksorta bez bufora O(n) potrzebnego w merge sort, kosztem stabilności i wydajności pamięci podręcznej.
Czym różni się heap sort od quicksorta?
Oba sortują w miejscu, ale quicksort ma najgorszy przypadek O(n²), a heap sort gwarantuje O(n log n). W praktyce quicksort jest zwykle szybszy dzięki lepszej lokalności pamięci podręcznej i mniejszej liczbie zamian, więc heap sort wybiera się głównie wtedy, gdy ograniczenie najgorszego przypadku musi być zagwarantowane.
Jaki jest związek sortowania przez kopcowanie z kolejką priorytetową?
Kopiec binarny to standardowa implementacja kolejki priorytetowej, a heap sort to w zasadzie wielokrotne zdejmowanie maksimum z takiej kolejki. Jeśli już trzymasz dane w kopcu, wyciąganie elementów po kolei daje posortowaną kolejność za darmo.
Czy heap sort potrzebuje kopca max czy kopca min?
Aby sortować rosnąco w miejscu, użyj kopca max: w każdym przebiegu największy element trafia na koniec, a posortowany ogon rośnie od prawej. Kopiec min dałby w miejscu kolejność malejącą albo rosnącą, jeśli wyciągasz elementy do osobnej tablicy.
Ilustracja języków programowania w Coddy

Opanuj algorytmy z Coddy

ZACZNIJ