Algorytm sortowania kopcowego (z Code in Python oraz C++)

โšก Inteligentne podsumowanie

Algorytm sortowania kopcowego sortuje tablicฤ™ poprzez zbudowanie kopca binarnego i wielokrotnetracumieszczajฤ…c jego wartoล›ฤ‡ gล‚รณwnฤ… w sekcji sortowanej. Ten zasรณb wyjaล›nia heapify, kopce maksymalne i minimalne, pseudokod i kompletne Python oraz C++ implementacje z analizฤ… zล‚oลผonoล›ci czasowej.

  • ๐ŸŒณ Podstawowa idea: Sortowanie kopcowe polega na stworzeniu kompletnego kopca binarnego, a nastฤ™pnie wielokrotnym powtรณrzeniutracts korzeล„ w celu wygenerowania posortowanej kolejnoล›ci.
  • ๐Ÿ”บ Heapify: Operacja heapify przywraca wล‚aล›ciwoล›ฤ‡ sterty poprzez zamianฤ™ping rodzic z wiฤ™kszym dzieckiem.
  • ๐Ÿ—ƒ๏ธ Pamiฤ™ฤ‡ masowa: Stos jest przechowywany w tablicy, w ktรณrej wฤ™zeล‚ o indeksie i ma dzieci o indeksach 2i+1 i 2i+2.
  • โฑ๏ธ. Zล‚oลผonoล›ฤ‡: Sortowanie kopcowe w kaลผdym przypadku zajmuje O(n log n) czasu i zuลผywa O(1) dodatkowej przestrzeni.
  • ๐Ÿ’ป Code Opatrzony: Pracujฤ…cy Python oraz C++ programy demonstrujฤ… heapify, budowฤ™ sterty i peล‚ne sortowanie.

Co to jest algorytm sortowania sterty?

Sortowanie kopcowe to jeden z popularnych i szybszych algorytmรณw sortowania. Opiera siฤ™ na strukturze danych kompletnego drzewa binarnego. Poszukamy elementu maksymalnego i umieล›cimy go na szczycie kopca maksymalnego. Umieล›cimy go w wฤ™ลบle nadrzฤ™dnym drzewa binarnego.

Powiedzmy, ลผe podana jest tablica, dane = [10,5, 7, 9, 4, 11, 45, 17, 60].

W tablicy, jeล›li i-ty (i=0,1,2,3 โ€ฆ) indeks jest wฤ™zล‚em nadrzฤ™dnym, to (2i+1) i (2i+2) bฤ™dฤ… lewym i prawym dzieckiem. Tworzenie kompletnego drzewa binarnego za pomocฤ… tej tablicy bฤ™dzie wyglฤ…daฤ‡ nastฤ™pujฤ…co:

Algorytm sortowania na stosie

Wykonamy proces heapify od poczฤ…tku do koล„ca tablicy. Poczฤ…tkowo, jeล›li przekonwertujemy tablicฤ™ na drzewo, bฤ™dzie wyglฤ…daฤ‡ jak powyลผej. Moลผemy zobaczyฤ‡, ลผe nie utrzymuje ลผadnej wล‚aล›ciwoล›ci heap (min-heap lub max heap). Otrzymamy posortowanฤ… tablicฤ™, wykonujฤ…c proces heapify dla wszystkich wฤ™zล‚รณw.

Zastosowanie sortowania stertowego

Oto kilka zastosowaล„ algorytmu sortowania sterty:

  • Konstrukcja โ€žkolejek priorytetowychโ€ wymaga sortowania sterty. Poniewaลผ heapsort utrzymuje element posortowany po kaลผdym wstawieniu.
  • Struktura danych sterty jest skuteczna w znajdowaniu kth najwiฤ™kszy element w danej tablicy.
  • Jฤ…dro Linuksa domyล›lnie uลผywa sortowania przez stertฤ™ algorytm sortowania poniewaลผ ma zล‚oลผonoล›ฤ‡ przestrzennฤ… O (1).

Utwรณrz sortowanie sterty na przykล‚adzie

Tutaj utworzymy kopiec maksymalny z nastฤ™pujฤ…cego kompletnego drzewa binarnego.

Utwรณrz sortowanie sterty na przykล‚adzie

Wฤ™zล‚y liล›ciowe to 17, 60, 4, 11 i 45. Nie majฤ… ลผadnych wฤ™zล‚รณw podrzฤ™dnych. Dlatego sฤ… wฤ™zล‚ami liล›ciowymi. Wiฤ™c rozpoczniemy metodฤ™ heapify od ich wฤ™zล‚a nadrzฤ™dnego. Oto kroki:

Krok 1) Wybierz poddrzewo znajdujฤ…ce siฤ™ najbardziej na lewo. Jeล›li wฤ™zล‚y podrzฤ™dne sฤ… wiฤ™ksze, zamieล„ wฤ™zeล‚ nadrzฤ™dny z wฤ™zล‚em podrzฤ™dnym.

Tutaj wฤ™zeล‚ nadrzฤ™dny to 9. Wฤ™zล‚y podrzฤ™dne to 17 i 60. Poniewaลผ 60 jest najwiฤ™ksze, 60 i 9 zostanฤ… zamienione miejscami, aby zachowaฤ‡ maksymalna sterta.

Utwรณrz sortowanie sterty na przykล‚adzie

Krok 2) Teraz poddrzewo znajdujฤ…ce siฤ™ najbardziej po lewej stronie jest stertowane. Nastฤ™pny wฤ™zeล‚ nadrzฤ™dny to 7. Ten rodzic ma dwa wฤ™zล‚y podrzฤ™dne, a najwiฤ™kszy ma 45. Zatem 45 i 7 zostanฤ… zamienione.

Utwรณrz sortowanie sterty na przykล‚adzie

Utwรณrz sortowanie sterty na przykล‚adzie

Krok 3) Wฤ™zล‚y 60 i 4 majฤ… wฤ™zeล‚ nadrzฤ™dny 5. Poniewaลผ โ€ž5โ€ jest mniejsze niลผ wฤ™zeล‚ podrzฤ™dny 60, zostanie ono zamienione.

Utwรณrz sortowanie sterty na przykล‚adzie

Utwรณrz sortowanie sterty na przykล‚adzie

Krok 4) Teraz wฤ™zeล‚ 5 ma wฤ™zeล‚ podrzฤ™dny 17,9. To nie jest zachowanie wล‚aล›ciwoล›ci max sterty. Zatem 5 zostanie zastฤ…pione 17.

Utwรณrz sortowanie sterty na przykล‚adzie

Krok 5) Wฤ™zeล‚ 10 zostanie zamieniony z wฤ™zล‚em 60, a nastฤ™pnie z wฤ™zล‚em 17. Proces bฤ™dzie wyglฤ…daล‚ nastฤ™pujฤ…co.

Utwรณrz sortowanie sterty na przykล‚adzie

Utwรณrz sortowanie sterty na przykล‚adzie

Krok 6) Do kroku 5 utworzyliล›my maksymalnฤ… stertฤ™. Kaลผdy wฤ™zeล‚ nadrzฤ™dny jest wiฤ™kszy niลผ jego wฤ™zล‚y podrzฤ™dne. Wฤ™zeล‚ gล‚รณwny ma maksymalnฤ… wartoล›ฤ‡ (60).

Uwaga: Aby utworzyฤ‡ posortowanฤ… tablicฤ™, musimy zastฤ…piฤ‡ wฤ™zeล‚ o maksymalnej wartoล›ci jego nastฤ™pcฤ….

Ten proces nazywa siฤ™ โ€žextract maksโ€. Poniewaลผ 60 to maksymalny wฤ™zeล‚, ustalimy jego pozycjฤ™ na 0-tym indeksie i utworzymy stertฤ™ bez wฤ™zล‚a 60.

Utwรณrz sortowanie sterty na przykล‚adzie

Utwรณrz sortowanie sterty na przykล‚adzie

Krok 7) Po usuniฤ™ciu 60, nastฤ™pnฤ… maksymalnฤ… wartoล›ciฤ… bฤ™dzie 45. Wykonamy proces โ€žExtracโ€žt Maxโ€ ponownie z wฤ™zล‚a 45.

Tym razem otrzymamy 45 i zastฤ…pimy wฤ™zeล‚ gล‚รณwny jego nastฤ™pcฤ… 17.

Musimy wykonaฤ‡ โ€žExtract Maxโ€, aลผ wszystkie elementy zostanฤ… posortowane.

Po wykonaniu tych krokรณw, aลผ do momentu, gdytracPo przeliczeniu wszystkich wartoล›ci maksymalnych otrzymamy nastฤ™pujฤ…cฤ… tablicฤ™.

Utwรณrz sortowanie sterty na przykล‚adzie

Co to jest sterta binarna?

Kopia binarna jest swego rodzaju kompletna drzewo binarne struktura danych. W tego rodzaju strukturze drzewa wฤ™zeล‚ nadrzฤ™dny jest wiฤ™kszy lub mniejszy niลผ wฤ™zล‚y podrzฤ™dne. Jeล›li wฤ™zeล‚ nadrzฤ™dny jest mniejszy, wรณwczas sterta nazywa siฤ™ โ€žStertฤ… minimalnฤ…โ€, a jeล›li wฤ™zeล‚ nadrzฤ™dny jest wiฤ™kszy, stertฤ™ nazywa siฤ™ โ€žStertฤ… maksymalnฤ…โ€.

Oto przykล‚ady minimalnej i maksymalnej sterty.

Minimalna sterta i maksymalna sterta
Minimalna sterta i maksymalna sterta

Jeล›li na powyลผszym rysunku zauwaลผysz โ€žMin Heapโ€, wฤ™zeล‚ nadrzฤ™dny jest zawsze mniejszy niลผ jego wฤ™zล‚y podrzฤ™dne. Na czele drzewa moลผemy znaleลบฤ‡ najmniejszฤ… wartoล›ฤ‡ 10.

Podobnie w przypadku โ€žMaksymalnej stertyโ€ wฤ™zeล‚ nadrzฤ™dny jest zawsze wiฤ™kszy niลผ wฤ™zล‚y podrzฤ™dne. Maksymalny element wystฤ™puje w wฤ™ลบle gล‚รณwnym โ€žMax Heapโ€.

Czym jest โ€žHeapifyโ€?

โ€žHeapifyโ€ to zasada kopca, ktรณra zapewnia pozycjฤ™ wฤ™zล‚a. W Heapify, maksymalny kopiec zawsze utrzymuje relacjฤ™ z rodzicem i dzieckiem, a wฤ™zeล‚ rodzica bฤ™dzie wiฤ™kszy niลผ wฤ™zล‚y dzieci.

Na przykล‚ad, jeล›li dodany zostanie nowy wฤ™zeล‚, musimy zmieniฤ‡ ksztaล‚t sterty. Moลผe jednak zaistnieฤ‡ koniecznoล›ฤ‡ zmiany lub zamiany wฤ™zล‚รณw albo przearanลผowania tablicy. Ten proces zmiany ksztaล‚tuping stertฤ™ nazywa siฤ™ โ€žheapifyโ€.

Oto przykล‚ad dziaล‚ania heapify:

Dodawanie nowego wฤ™zล‚a i heapify
Dodawanie nowego wฤ™zล‚a i heapify

Oto kroki dla heapify:

Krok 1) Dodano wฤ™zeล‚ 65 jako prawy element podrzฤ™dny wฤ™zล‚a 60.

Krok 2) Sprawdลบ, czy nowo dodany wฤ™zeล‚ jest wiฤ™kszy niลผ rodzic.

Krok 3) Poniewaลผ jest wiฤ™kszy niลผ wฤ™zeล‚ nadrzฤ™dny, zamieniliล›my wล‚aล›ciwe dziecko z jego rodzicem.

Jak zbudowaฤ‡ stertฤ™

Zanim zbudujemy stos lub utworzymy stos drzewa, musimy wiedzieฤ‡, jak bฤ™dziemy go przechowywaฤ‡. Poniewaลผ stos jest kompletnym drzewem binarnym, lepiej jest uลผyฤ‡ szyk do przechowywania danych sterty.

Zaล‚รณลผmy, ลผe tablica zawiera ล‚ฤ…cznie n elementรณw. Jeล›li โ€žiโ€ indeks jest wฤ™zล‚em nadrzฤ™dnym, wรณwczas lewy wฤ™zeล‚ bฤ™dzie miaล‚ indeks (2i+1), a prawy wฤ™zeล‚ bฤ™dzie w indeksie (2i+2). Zakล‚adamy, ลผe indeks tablicy zaczyna siฤ™ od 0.

Uลผywajฤ…c tego, zapiszemy maksymalnฤ… iloล›ฤ‡ stosu w nastฤ™pujฤ…cy sposรณb:

Oparta na tablicach reprezentacja maksymalnej sterty
Oparta na tablicy reprezentacja maksymalnej sterty

Algorytm heapify utrzymuje wล‚aล›ciwoล›ฤ‡ heap. Jeล›li rodzic nie ma wartoล›ci skrajnej (mniejszej lub wiฤ™kszej), zostanie zamieniony z najbardziej skrajnym wฤ™zล‚em podrzฤ™dnym.

Oto kroki sล‚uลผฤ…ce do utworzenia kopca maksymalnego:

Krok 1) Zacznij od wฤ™zล‚a liล›cia.

Krok 2) Znajdลบ maksimum miฤ™dzy rodzicem a dzieฤ‡mi.

Krok 3) Zamieล„ wฤ™zล‚y, jeล›li wฤ™zeล‚ podrzฤ™dny ma wiฤ™kszฤ… wartoล›ฤ‡ niลผ wฤ™zeล‚ nadrzฤ™dny.

Krok 4) Przejdลบ o jeden poziom wyลผej.

Krok 5) Postฤ™puj zgodnie z krokami 2,3,4, aลผ osiฤ…gniemy indeks 0 lub posortuj caล‚e drzewo.

Oto pseudokod dla rekurencyjnego heapify (maksymalny heap):

def heapify():
  inputโ†’ array, size, i
  largest = i
  left = 2*i + 1
  right = 2*i + 2
if left<n and array[largest ] < array[left]:
  largest = left
if right<n and array[largest ] < array[right]:
  largest = right
If largest not equals i:
  swap(array[i],array[largest])
  heapify(array,n,largest)

Rzekomy Code dla sortowania kopcowego

Oto pseudokod algorytmu sortowania sterty:

Heapify(numbers as an array, n as integer, i as integer):
  largest = i
  left = 2i+1
  right= 2i+2
if(left<=n) and (numbers[i]<numbers[left])
  largest=left
if(right<=n) and (numbers[i]<numbers[right])
  largest=right
if(largest  != i)
  swap(numbers[i], numbers[largest])
  Heapify(numbers,n,largest)
HeapSort(numbers as an array):
  n= numbers.size()
for i in range n/2 to 1
  Heapify(numbers,n,i)
for i in range n to 2
  Swap numbers[i] with numbers[1]
  Heapify(numbers,i,0)

Przykล‚ad sortowania kopcowego Code in C++

#include <iostream>
using namespace std;
void display(int arr[], int n)
{
    for (int i = 0; i < n; i++)
    {
        cout << arr[i] << "\t";
    }
    cout << endl;
}
void heapify(int numbers[], int n, int i)
{
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;
    if (left < n && numbers[left] < numbers[largest])
    {
        largest = left;
    }
    if (right < n && numbers[right] < numbers[largest])
    {
        largest = right;
    }
    if (largest != i)
    {
	//uncomment the following line to see details in output
        //cout<<"Swapping "<< numbers[i]<< " and "<<numbers[largest]<<endl;
        swap(numbers[i], numbers[largest]);
        heapify(numbers, n, largest);
    }
}
void heapSort(int numbers[], int n)
{
    for (int i = n/2 - 1; i >= 0; i--)
    {
        heapify(numbers, n, i);
//uncomment the following line to see details in output
 //cout<<"Heapify:\t";
  //display(numbers,n);
    }
    for (int i = n - 1; i >= 0; i--)
    {
        swap(numbers[0], numbers[i]);
        heapify(numbers, i, 0);
    }
}
int main()
{
    int numbers[] = { 10,5, 7, 9, 4, 11, 45, 17, 60};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    cout<<"Initial Array:\t";
    display(numbers,size);
    heapSort(numbers, size);
    cout<<"Sorted Array (descending order):\t";
    display(numbers, size);
}

Wyjล›cie:

Initial Array:  10      5       7       9       4       11      45      17      60
Sorted Array (descending order):  60      45      17      11      10      9       7       5       4

Przykล‚ad sortowania kopcowego Code in Python

def display(arr):
    for i in range(len(arr)):
    print(arr[i], end = "\t")
print()
def heapify(numbers, n, i):
    largest = i
left = 2 * i + 1
right = 2 * i + 2
if left < n and numbers[left] < numbers[largest]:
    largest = left
if right < n and numbers[right] < numbers[largest]:
    largest = right
if largest != i:
    numbers[i], numbers[largest] = numbers[largest], numbers[i]
heapify(numbers, n, largest)
def heapSort(items, n):
    for i in range(n //2,-1,-1):
        heapify(items, n, i) for i in range(n - 1, -1, -1):
        items[0], items[i] = items[i], items[0] heapify(items, i, 0) numbers = [10, 5, 7, 9, 4, 11, 45, 17, 60] print("Initial List:\t", end = "") display(numbers) print("After HeapSort:\t", end = "") heapSort(numbers, len(numbers)) display(numbers)

Wyjล›cie:

Initial List:   10      5       7       9       4       11      45      17      60
After HeapSort: 60      45      17      11      10      9       7       5       4

Analiza zล‚oลผonoล›ci czasowej i przestrzennej sortowania kopcowego

Istnieje zล‚oลผonoล›ฤ‡ czasowa i zล‚oลผonoล›ฤ‡ przestrzenna, ktรณre moลผemy analizowaฤ‡ dla sortowania kopcowego. Dla zล‚oลผonoล›ci czasowej mamy nastฤ™pujฤ…ce przypadki:

  1. Najlepsza sprawa
  2. ลšrednia sprawa
  3. Najgorszy przypadek

Sterta jest zaimplementowana na kompletnym drzewie binarnym. Zatem na dolnym poziomie drzewa binarnego bฤ™dzie maksymalna liczba wฤ™zล‚รณw. Jeล›li dolny poziom ma n wฤ™zล‚รณw, wรณwczas wyลผszy poziom bฤ™dzie miaล‚ n/2 wฤ™zล‚รณw.

Analiza zล‚oลผonoล›ci czasu i przestrzeni

W tym przykล‚adzie poziom 3 ma cztery elementy, poziom 2 ma dwa elementy, a poziom 1 ma jeden element. Jeล›li istnieje caล‚kowita liczba n elementรณw, wysokoล›ฤ‡ lub caล‚kowity poziom bฤ™dzie wynosiฤ‡ Zaloguj2(N). Zatem wstawienie pojedynczego elementu moลผe wymagaฤ‡ maksymalnie iteracji Log(n).

Gdy chcemy pobraฤ‡ maksymalnฤ… wartoล›ฤ‡ ze sterty, po prostu bierzemy wฤ™zeล‚ gล‚รณwny. Nastฤ™pnie ponownie uruchamiamy heapify. Kaลผda heapify pobiera Zaloguj2(n) czas. Byล‚ytracOsiฤ…gniฤ™cie maksimum zajmuje O(1) czasu.

Najlepszy przypadek zล‚oลผonoล›ci czasowej dla algorytmu sortowania kopcowego

Kiedy wszystkie elementy tablicy sฤ… juลผ posortowane, zbudowanie sterty zajmie O(n) czasu. Poniewaลผ jeล›li lista jest posortowana, wstawienie elementu zajmie staล‚y czas, czyli O(1).

Zatem w najlepszym przypadku utworzenie maksymalnej lub minimalnej sterty zajmie O(n) czasu.

ลšrednia zล‚oลผonoล›ฤ‡ czasowa przypadku dla algorytmu sortowania kopcowego

Wstawianie elementu lub extracOsiฤ…gniฤ™cie maksymalnego kosztu kosztuje O(log(n)). Zatem ล›rednia zล‚oลผonoล›ฤ‡ czasowa dla algorytmu sortowania kopcowego wynosi O(n log(n)).

Najgorszy przypadek zล‚oลผonoล›ci czasowej dla algorytmu sortowania kopcowego

Podobnie jak w przypadku przeciฤ™tnym, w najgorszym scenariuszu moglibyล›my wykonaฤ‡ heapify n razy. Kaลผde heapify bฤ™dzie kosztowaฤ‡ O(log(n)) czasu. Tak wiฤ™c zล‚oลผonoล›ฤ‡ czasowa w najgorszym przypadku bฤ™dzie wynosiฤ‡ O(n log(n)).

Zล‚oลผonoล›ฤ‡ przestrzenna dla algorytmu sortowania kopcowego

Sortowanie kopcowe to algorytm zaprojektowany w miejscu. Oznacza to, ลผe do wykonania zadania nie jest potrzebna ลผadna dodatkowa ani tymczasowa pamiฤ™ฤ‡. Jeล›li przyjrzymy siฤ™ implementacji, zauwaลผymy, ลผe uลผyliล›my swap() do wykonania wymiany wฤ™zล‚รณw. Nie byล‚a potrzebna ลผadna inna lista ani tablica. Zatem zล‚oลผonoล›ฤ‡ przestrzenna wynosi O(1).

FAQ

Sortowanie kopcowe nie jest stabilnym algorytmem sortowania, poniewaลผ budowanie itracPobieranie z kopca moลผe zmieniฤ‡ kolejnoล›ฤ‡ rรณwnych elementรณw. Jeล›li zachowanie pierwotnej kolejnoล›ci rรณwnych kluczy ma znaczenie, lepszym wyborem bฤ™dzie stabilny algorytm, taki jak sortowanie przez scalanie.

Sortowanie kopcowe gwarantuje czas O(n log n) we wszystkich przypadkach i zuลผywa O(1) dodatkowej przestrzeni. Szybkie sortowanie jest zazwyczaj szybsze w praktyce, ale moลผe spaล›ฤ‡ do O(nยฒ) w przypadku bล‚ฤ™dnych osi obrotu. Sortowanie kopcowe wymaga nieco szybkoล›ci w zamian za niezawodnoล›ฤ‡ w najgorszym przypadku.

Zarรณwno sortowanie kopcowe, jak i sortowanie przez scalanie dziaล‚ajฤ… w czasie O(n log n). Sortowanie kopcowe sortuje w miejscu z dodatkowฤ… przestrzeniฤ… O(1), ale jest niestabilne. Sortowanie przez scalanie jest stabilne, ale wymaga dodatkowej przestrzeni O(n) do scalania.

Tutorzy AI mogฤ… animowaฤ‡ proces heapify, pokazywaฤ‡, jak powstaje maksymalny stos i trackaลผdy byล‚ytracKrok t-max. Ta wizualna, interaktywna pomoc uล‚atwia poczฤ…tkujฤ…cym zrozumienie, jak sortowanie kopcowe porzฤ…dkuje tablicฤ™.

Tak. Asystenci kodowania AI mogฤ… tล‚umaczyฤ‡ implementacjฤ™ sortowania kopcowego miฤ™dzy jฤ™zykami takimi jak C++, Python, Java podczas gdy keeping Logika nienaruszona. Nadal powinieneล› skompilowaฤ‡ i przetestowaฤ‡ przekonwertowany kod, aby potwierdziฤ‡ poprawnoล›ฤ‡ wynikรณw.

Podsumuj ten post nastฤ™pujฤ…co: