Heap rendezési algoritmus (a Code in Python és a C++)

⚡ Okos összefoglaló

A halomrendezési algoritmus egy tömböt úgy rendez, hogy bináris halmot épít fel, és ismételten végrehajtja a műveletet.traca gyökérértékét a rendezett szakaszba illeszti. Ez az erőforrás elmagyarázza a heapify, max és min heap-eket, a pszeudokódot és a teljes Python és a C++ időbeli komplexitáselemzéssel végzett megvalósítások.

  • ???? Alapötlet: A halomrendezés egy teljes bináris halmot épít fel, majd ismételten ex-t végez.traca gyökeret használja rendezett sorrend létrehozásához.
  • 🔺 Heapify: A heapify művelet swap segítségével visszaállítja a heap tulajdonságot.ping egy szülő a nagyobb gyermekével.
  • 🗃️ Tömbtárolás: Egy heap egy tömbben tárolódik, ahol az i indexű csomópontnak 2i+1 és 2i+2 indexű gyermekei vannak.
  • ⏱️ Bonyolultság: A halomrendezés minden esetben O(n log n) idő alatt fut le, és O(1) extra helyet használ.
  • ???? Code Biztosítani: Dolgozó Python és a C++ A programok bemutatják a heapify-t, a heap building-et és a teljes fajta műveleteket.

Mi az a kupacrendezési algoritmus?

A halomrendezés (heap sort) az egyik népszerű és leggyorsabb rendezési algoritmus. A teljes bináris fa adatstruktúrájára épül. Megkeressük a maximális elemet, és azt a maximális halom tetejére tesszük. A bináris fa szülőcsomópontjára tesszük.

Tegyük fel, hogy adott egy tömb, adatok = [10,5].

A tömbben, ha az i-edik (i=0,1,2,3 …) index szülőcsomópont, akkor (2i+1) és (2i+2) lesz a bal és a jobb oldali gyermek. Egy teljes bináris fa létrehozása ezzel a tömbbel így fog kinézni:

Halomrendezési algoritmus

A heapify folyamatot a tömb elejétől a végéig végezzük el. Kezdetben, ha a tömböt fává alakítjuk, az a fentihez hasonlóan fog kinézni. Láthatjuk, hogy nem tart fenn semmilyen kupac tulajdonságot (min-heap vagy max heap). A rendezett tömböt úgy kapjuk meg, hogy az összes csomópontnál végrehajtjuk a heapify folyamatot.

A Heap rendezés alkalmazása

Íme a kupacrendezési algoritmus néhány felhasználási módja:

  • A „Priority Queues” felépítéséhez halomrendezésre van szükség. Mivel a heapsort minden egyes beillesztés után rendezve tartja az elemeket.
  • A kupac adatstruktúra hatékonyan keresi a kth a legnagyobb elem egy adott tömbben.
  • A Linux Kernel a kupac rendezést használja alapértelmezettként rendezési algoritmus mivel O (1) térkomplexitású.

Hozzon létre kupacrendezést a példával

Itt készítünk egy max kupacot a következő teljes bináris fából.

Hozzon létre kupacrendezést a példával

A levél csomópontjai 17, 60, 4, 11 és 45. Nincsenek alárendelt csomópontjaik. Ezért levél csomópontok. Tehát a heapify metódust a szülőcsomópontjukból indítjuk. Íme a lépések:

Step 1) Válassza ki a bal szélső részfát. Ha a gyermek csomópontok nagyobbak, cserélje fel a szülőcsomópontot a gyermek csomóponttal.

Itt a szülőcsomópont a 9. A gyermekcsomópontok pedig a 17 és a 60. Mivel a 60 a legnagyobb, a 60 és 9 felcserélődik, hogy fenntartsák a max halom.

Hozzon létre kupacrendezést a példával

Step 2) Most a bal szélső részfa halmozva van. A következő szülőcsomópont a 7. Ennek a szülőnek két gyermekcsomópontja van, a legnagyobb pedig 45. Tehát a 45 és a 7 felcserélődik.

Hozzon létre kupacrendezést a példával

Hozzon létre kupacrendezést a példával

Step 3) A 60-as és 4-es csomópontnak az 5-ös szülőcsomópontja van. Mivel az „5” kisebb, mint a 60-as gyermekcsomópont, felcserélődik.

Hozzon létre kupacrendezést a példával

Hozzon létre kupacrendezést a példával

Step 4) Most az 5. csomópont rendelkezik a 17,9 gyermekcsomóponttal. Ez nem tartja fenn a max kupac tulajdonságot. Tehát az 5 helyett 17 lesz.

Hozzon létre kupacrendezést a példával

Step 5) A 10-es csomópont felcserélődik 60-ra, majd 17-re. A folyamat a következőképpen fog kinézni.

Hozzon létre kupacrendezést a példával

Hozzon létre kupacrendezést a példával

Step 6) Az 5. lépésig létrehoztuk a maximális kupacot. Minden szülőcsomópont nagyobb, mint a gyermekcsomópontjai. A gyökércsomópont maximális értéke (60).

Jegyzet: A rendezett tömb létrehozásához le kell cserélnünk a max értékű csomópontot az utódjára.

Ezt a folyamatot "extract-max”. Mivel a 60 a maximális csomópont, a pozícióját a 0. indexhez rögzítjük, és létrehozzuk a kupacot a 60-as csomópont nélkül.

Hozzon létre kupacrendezést a példával

Hozzon létre kupacrendezést a példával

Step 7) Mivel 60-at eltávolítunk, a következő maximális érték 45 lesz. A következő folyamatot fogjuk végrehajtani: „Példatrac„t Max” ismét a 45-ös csomópontból.

Ezúttal 45-öt kapunk, és lecseréljük a gyökércsomópontot az utódjára, a 17-re.

teljesítenünk kell"Extract Max”-ig, amíg az összes elem nincs rendezve.

Miután elvégeztük ezeket a lépéseket, amíg ki nem szabadulunktracAz összes maximális értéket figyelembe véve a következő tömböt kapjuk.

Hozzon létre kupacrendezést a példával

Mi az a bináris kupac?

A bináris kupac egyfajta teljes bináris fa adatszerkezet. Az ilyen típusú fastruktúrákban a szülőcsomópont nagyobb vagy kisebb, mint a gyermek csomópontok. Ha a szülőcsomópont kisebb, akkor a kupacot „Minimális kupacnak”, és ha a szülőcsomópont nagyobb, a kupacot „Max. kupacnak” nevezik.

Íme példák a minimális kupacra és a maximális kupacra.

Min Heap és Max Heap
Min Heap és Max Heap

A fenti ábrán, ha a „Min Heap”-et észleli, a szülőcsomópont mindig kisebb, mint a gyermek csomópontok. A fa élén a legkisebb 10-es értéket találjuk.

Hasonlóképpen, a „Max Heap” esetében a szülőcsomópont mindig nagyobb, mint a gyermek csomópontok. A maximális elem a „Max Heap” fejcsomópontjában található.

Mi az a „Heapify”?

„Heapify” a kupac elve, amely biztosítja a csomópont helyzetét. A Heapify-ban a maximális kupac mindig kapcsolatot tart fenn a szülővel és a gyermekkel, vagyis a szülőcsomópont nagyobb lesz, mint a gyermekcsomópont.

Például, ha egy új csomópontot adunk hozzá, át kell alakítanunk a heap-et. Előfordulhat azonban, hogy meg kell változtatnunk vagy fel kell cserélnünk a csomópontokat, vagy át kell rendeznünk a tömböt. Ez az átrendezési folyamatping Egy halmot „heapificálásnak” nevezünk.

Íme egy példa a heapify működésére:

Új csomópont hozzáadása és Heapify
Új csomópont hozzáadása és halmozás

Íme a heapify lépései:

Step 1) A 65. csomópont hozzáadva a 60. csomópont megfelelő gyermekeként.

Step 2) Ellenőrizze, hogy az újonnan hozzáadott csomópont nagyobb-e, mint a szülő.

Step 3) Mivel nagyobb, mint a szülőcsomópont, a megfelelő gyermeket felcseréltük a szülővel.

Hogyan építsük fel a kupacot

A kupac építése vagy a fa felhalmozása előtt tudnunk kell, hogyan fogjuk tárolni. Mivel a kupac egy teljes bináris fa, jobb, ha egy sor a kupac adatainak tárolására.

Tegyük fel, hogy egy tömb összesen n elemet tartalmaz. Ha az „i” index egy szülőcsomópont, akkor a bal oldali csomópont az indexen lesz (2i+1), és a jobb oldali csomópont az indexen lesz (2i+2). Feltételezzük, hogy a tömb indexe 0-tól kezdődik.

Ennek segítségével tároljunk egy max kupacot egy tömbszerű következőben:

A Max Heap tömb alapú ábrázolása
A max kupac tömb alapú ábrázolása

A heapify algoritmus fenntartja a kupac tulajdonságot. Ha a szülő nem rendelkezik a szélső értékkel (kisebb vagy nagyobb), akkor a rendszer a legszélsőségesebb gyermekcsomópontra cseréli.

Íme a lépések a maximális kupac felhalmozásához:

Step 1) Kezdje a levél csomópontjától.

Step 2) Találd meg a maximumot a szülő és a gyerekek között.

Step 3) Cserélje ki a csomópontokat, ha a gyermek csomópont értéke nagyobb, mint a szülőé.

Step 4) Menj egy szinttel feljebb.

Step 5) Kövesse a 2,3,4, 0, XNUMX lépéseket, amíg el nem éri a XNUMX indexet, vagy rendezi a teljes fát.

Íme a rekurzív halomozás pszeudokódja (max. kupac):

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)

Pszeudo Code Heap Rendezéshez

Íme a kupacrendezési algoritmus pszeudokódja:

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)

Példa a halomrendezésre 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);
}

output:

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

Példa a halomrendezésre 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)

output:

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

A Heap Sort idő és tér komplexitásának elemzése

Létezik az időbonyolultság és a térbonyolultság, amelyeket a kupacrendezéshez elemezhetünk. Az időbonyolítás érdekében a következő eseteket vesszük figyelembe:

  1. Legjobb eset
  2. Átlagos eset
  3. Legrosszabb esetben

A kupac egy teljes bináris fán van megvalósítva. Tehát a bináris fa alsó szintjén a csomópontok maximális száma lesz. Ha az alsó szinten n csomópont van, akkor a fenti szinten n/2 csomópont lesz.

Idő és tér komplexitás elemzése

Ebben a példában a 3. szint négy elemet tartalmaz, a 2. szint két elemet, az 1. szint pedig egy elemet tartalmaz. Ha összesen n darab elem van, akkor a magasság vagy a teljes szint a következő lesz Bejelentkezés2(n). Tehát egyetlen elem beszúrása legfeljebb Log(n) iterációt igényelhet.

Ha a kupacból a maximális értéket akarjuk venni, csak a gyökércsomópontot vesszük. Ezután futtassa újra a heapify-t. Minden halmozódást vesz igénybe Bejelentkezés2(N) idő. PéldáultracA maximum elérése O(1) időt vesz igénybe.

A halomrendezési algoritmus legjobb eset-időbeli összetettsége

Amikor az összes elem már rendezve van a tömbben, O(n) időbe telik a kupac felépítése. Mert ha a lista rendezve van, akkor egy elem beszúrása állandó időt vesz igénybe, ami O(1).

Tehát a legjobb esetben O(n) időbe telik egy max-halom vagy min-heap létrehozása.

Átlagos eset-idő komplexitás a kupacrendezési algoritmushoz

Elem vagy ex beszúrásatracA maximum kiszámítása O(log(n)) időt vesz igénybe. Tehát a halomrendezési algoritmus átlagos esetidő-bonyolultsága: O(n log(n)).

A legrosszabb eset bonyolultsága a halomrendezési algoritmushoz

Az átlagos esethez hasonlóan a legrosszabb forgatókönyv esetén n-szeres halmozódást hajthatunk végre. Minden halmozódás O(log(n)) időbe kerül. Tehát a legrosszabb eset lesz az időbonyolítás O(n log(n)).

Helykomplexitás a kupacrendezési algoritmushoz

A halomrendezés egy helyben tervezett algoritmus. Ez azt jelenti, hogy a feladat végrehajtásához nincs szükség extra vagy ideiglenes memóriára. Ha látjuk a megvalósítást, észrevesszük, hogy a swap ()-t használtuk a csomópontok cseréjéhez. Más listára vagy tömbre nem volt szükség. Tehát a tér komplexitása O(1).

GYIK

A halomrendezés nem stabil rendezési algoritmus, mivel az építkezés és az extracA halomból történő kinyerés átrendezheti az egyenlő elemeket. Ha az egyenlő kulcsok eredeti sorrendjének megőrzése fontos, akkor egy stabil algoritmus, mint például az összevont rendezés, jobb választás.

A heap rendezés minden esetben O(n log n) időt garantál, és O(1) extra helyet használ. A gyorsrendezés a gyakorlatban általában gyorsabb, de rossz pivotok esetén O(n²)-re degradálódhat. A heap rendezés némi sebességet cserél a megbízható legrosszabb esetre.

Mind a halomrendezés, mind az összevont rendezés O(n log n) időt vesz igénybe. A halomrendezés O(1) plusz hellyel rendez, de instabil. Az összevont rendezés stabil, de az egyesítéshez O(n) plusz helyre van szüksége.

A mesterséges intelligencia által támogatott oktatók animálhatják a heapify folyamatot, megmutathatják, hogyan alakul ki a max heap, és tracminden extract-max lépés. Ez a vizuális, interaktív súgó megkönnyíti a kezdők számára, hogy megértsék, hogyan rendezi a halomrendezés a tömböket.

Igen. A mesterséges intelligencia által fejlesztett kódolóasszisztensek képesek lefordítani egy halomrendezési implementációt különböző nyelvek között, például C++, Pythonés Java miközben keeping a logika ép. A konvertált kódot továbbra is le kell fordítani és tesztelni kell a helyes kimenet megerősítése érdekében.

Foglald össze ezt a bejegyzést a következőképpen: