Algoritmul de sortare prin inserție cu C, C++, Java, Python Exemple

⚡ Rezumat inteligent

Sortarea prin inserție este o metodă de sortare in-place, bazată pe comparații, care construiește o listă sortată element cu element. Este stabilă, adaptivă, ușor de implementat și potrivită pentru seturi de date mici sau aproape sortate în practică.

  • 📥 Ideea de bază: Sortarea prin inserție selectează fiecare element și îl deplasează la stânga până când acesta se află în poziția corectă în sublista deja sortată.
  • 🔁 Insera OperaTION: Comparațiile repetate de tip „swap-with-left” determină algoritmul, crescând regiunea sortată cu un element per trecere a buclei exterioare.
  • Complexitatea timpului: Cel mai bun caz se execută în O(n) pentru date deja sortate, în timp ce cazurile cele mai rele și medii ajung la O(n^2) pentru intrări inversate sau amestecate.
  • Proprietăți: Algoritmul este online, in situ, stabil și adaptiv, ceea ce îl face previzibil pentru inserții în flux continuu și matrici parțial sortate.
  • 🧪 Code Acoperire: Implementările de referință sunt furnizate în C, C++ și Python astfel încât elevii să poată compara structurile buclelor și să schimbe mecanicile una lângă alta.
  • 🤖 Unghiul AI: Asistenții moderni cu inteligență artificială vizualizează trecerile de sortare prin inserție și le recomandă atunci când matricele de intrare sunt scurte sau aproape ordonate.

Ce este Insertion Sort?

Sortarea prin inserție este unul dintre algoritmii de sortare prin comparație utilizați pentru sortarea elementelor prin iterarea pe câte un element pe rând și plasarea elementului în poziția corectă într-o regiune deja ordonată.

Fiecare element este inserat secvențial într-o listă deja sortată. Dimensiunea inițială a listei deja sortate este unu. Algoritmul de sortare prin inserție asigură că primele k elemente sunt sortate după a k-a iterație a buclei exterioare.

Deoarece sortarea prin inserție construiește rezultatul incremental, este intuitiv de învățat, ușor de depanat și o bază puternică pentru intrări foarte mici, unde algoritmi mai complecși ar adăuga costuri suplimentare fără câștiguri măsurabile.

Caracteristicile algoritmului de sortare prin inserție

Algoritmul de sortare prin inserție are următoarele caracteristici importante care explică comportamentul său pe sarcini de lucru reale:

  • Este o tehnică de sortare stabilă, deci nu modifică ordinea relativă a elementelor egale.
  • Este eficient pentru seturi de date mai mici, dar nu și pentru liste mai mari unde domină creșterea pătratică.
  • Sortarea prin inserție este adaptivă, ceea ce reduce numărul total de pași dacă datele de intrare sunt parțial sortate. Mulțime este furnizat ca intrare pentru a-l face eficient, deoarece accesul aleator permite deplasări constante în timp în timpul buclei interne.
  • Este un algoritm in-place, deci nu necesită stocare auxiliară proporțională cu dimensiunea intrării.

Având în vedere aceste trăsături, următoarea secțiune explică operația de inserare de bază care alimentează fiecare pas al algoritmului.

Cum se inserează Operamunca de tion?

În algoritmul de sortare prin inserție, operația de inserare este utilizată pentru a sorta elementele nesortate. Aceasta ajută la inserarea unui element nou într-o listă deja sortată, păstrând în același timp ordinea existentă a regiunii sortate.

Pseudocod al operației de inserare:

Să considerăm o listă A de N elemente.

// Insert A[N-1] into sorted sublist A[0..N-2]
for i = N-1 to 1:
    if A[i] < A[i-1], then swap A[i] and A[i-1]
    else stop

Insera Operamunca de tion

În exemplul de mai sus, un nou element 6 este inserat într-o listă deja sortată. Pașii următori trace bucla interioară pe măsură ce noul element migrează la stânga către poziția sa corectă.

Pas 1) În comparație cu elementul adiacent stâng al lui A[5], 9 > 6, schimbăm poziția lui 9 și 6. Acum elementul 6 este mutat în A[4].

Pas 2) Acum, comparăm A[4] și A[3] și constatăm că A[3] > A[4], așa că inversăm din nou poziția lui 6 și 8.

Pas 3) Acum comparați A[3] și A[2]. Când A[2] > A[3], inversăm poziția lui 7 și 6.

Pas 4) Comparăm A[1] și A[2]. Când A[1] < A[2], elementul adiacent la stânga nu mai este mai mare. Concluzionăm că 6 este introdus corect și oprim bucla interioară aici.

Cum funcționează sortarea inserției

Operația de inserare discutată mai sus este coloana vertebrală a sortării prin inserție. Procedura de inserare este executată pe fiecare element și, la final, obținem lista sortată pe măsură ce regiunea sortată crește cu un element la fiecare trecere externă.

Lucrări de sortare prin inserare

Figura de mai sus demonstrează funcționarea sortării prin inserție într-o structură de date. Inițial, în sublista sortată se află un singur element, adică 4. După inserarea lui A[1], adică 3, dimensiunea sublistei sortate crește la 2, iar algoritmul continuă acest model până când fiecare element a fost plasat.

Odată ce fluxul conceptual a fost stabilit, următoarele secțiuni prezintă implementări concrete în C++, C și Python astfel încât să puteți compara structurile de bucle între diferite limbaje.

C++ Program de sortare prin inserare

C++ Implementarea de mai jos folosește două bucle imbricate: bucla exterioară selectează următorul element nesortat, iar bucla interioară îl deplasează la stânga până când este găsită poziția corectă.

#include <iostream>
using namespace std;

int main(){
    //unsorted list
    int unsorted[] = {9,8,7,6,5,4,3,3,2,1};

    //size of list
    int size_unsorted = sizeof(unsorted) / sizeof(unsorted[0]);

    //printing unsorted list
    cout << "\nUnsorted: ";
    for(int i = 0 ; i < size_unsorted ; i++){
        cout << unsorted[i] << " ";
    }

    int current_element,temp;

    for(int i = 1; i < size_unsorted; i++){
        current_element = unsorted[i];
        for(int j = i-1; j >= 0 && unsorted[j] > current_element; j--){
            //swapping if current element is lesser
            temp = unsorted[j+1];
            unsorted[j+1] = unsorted[j];
            unsorted[j] = temp;
        }
    }

    //printing sorted list
    cout << "\nSorted: ";
    for(int i = 0 ; i < size_unsorted ; i++){
        cout << unsorted[i] << " ";
    }

    return 0;
}

ieșire:

Unsorted: 9 8 7 6 5 4 3 3 2 1
Sorted: 1 2 3 3 4 5 6 7 8 9

C Code pentru sortare prin inserție

Aceeași logică se traduce direct în C. Standardul printf apelurile înlocuiesc ieșirea fluxului, dar modelul de swap din interiorul buclei interioare este identic cu C++ versiune.

#include <stdio.h>
int main() {
    //unsorted list
    int unsorted[] = {9,8,7,6,5,4,3,3,2,1};

    //size of list
    int size_unsorted = sizeof(unsorted) / sizeof(unsorted[0]);

    //printing unsorted list
    printf("\nUnsorted: ");
    for(int i = 0 ; i < size_unsorted ; i++){
        printf("%d ", unsorted[i]);
    }

    int current_element, temp;

    for(int i = 1; i < size_unsorted; i++){
        current_element = unsorted[i];
        for(int j = i-1; j >= 0 && unsorted[j] > current_element; j--){
            //swapping if current element is lesser
            temp = unsorted[j+1];
            unsorted[j+1] = unsorted[j];
            unsorted[j] = temp;
        }
    }

    //printing sorted list
    printf("\nSorted: ");
    for(int i = 0 ; i < size_unsorted ; i++){
        printf("%d ", unsorted[i]);
    }

    return 0;
}

ieșire:

Output:
Unsorted: 9 8 7 6 5 4 3 3 2 1
Sorted: 1 2 3 3 4 5 6 7 8 9

Python Program de sortare prin inserare

Python suportă schimbarea tuplurilorping într-o singură expresie, deci bucla interioară este mai compactă decât C-ul său și C++ omologi, păstrând în același timp același comportament algoritmic.

#unsorted list
unsorted = [9,8,7,6,5,4,3,3,2,1]

#size of list
size_unsorted = len(unsorted)

#printing unsorted list
print("\nUnsorted: ", end="")
for i in range(size_unsorted):
    print(unsorted[i], end=" ")

for i in range(1, size_unsorted):
    current_element = unsorted[i]
    j = i - 1
    while j >= 0 and unsorted[j] > current_element:
        #swapping if current element is lesser
        unsorted[j+1], unsorted[j] = unsorted[j], unsorted[j+1]
        j -= 1

#printing sorted list
print("\nSorted: ", end="")
for i in range(size_unsorted):
    print(unsorted[i], end=" ")

ieșire:

Unsorted: 9 8 7 6 5 4 3 3 2 1
Sorted: 1 2 3 3 4 5 6 7 8 9

Proprietăți ale sortării inserției

Iată câteva proprietăți importante ale sortării prin inserție care vă ajută să decideți când este instrumentul potrivit:

  • online: Sortarea prin inserție poate sorta elementele pe măsură ce le primește. Dacă am sortat deja o listă de elemente și adăugăm mai multe elemente la listă, atunci nu este nevoie să rulăm din nou întreaga procedură de sortare. În schimb, iterăm doar pe elementele nou adăugate.
  • La loc: Complexitatea spațială a algoritmului de sortare prin inserție este constantă și nu necesită spațiu suplimentar. Acest algoritm sortează elementele la locul lor.
  • Grajd: În sortarea prin inserție, nu inversăm elementele dacă valorile lor sunt egale. De exemplu, dacă două elemente, x și y, sunt egale și x apare înaintea lui y în lista nesortată, atunci în lista sortată, x va apărea în continuare înaintea lui y. Acest lucru face ca sortarea prin inserție să fie stabilă.
  • Adaptiv: A algoritm de sortare este adaptivă dacă durează mai puțin atunci când elementele de intrare sau un subset de elemente sunt deja sortate. După cum am discutat mai sus, cel mai bun timp de execuție al sortării prin inserție este O(N), iar cel mai slab timp de execuție este O(N^2). Sortarea prin inserție este unul dintre algoritmii de sortare adaptivă.

Complexitatea sortării inserției

Discuția despre complexitate de mai jos acoperă atât utilizarea memoriei, cât și timpul de execuție, astfel încât să puteți poziționa sortarea prin inserție în raport cu alternative precum Bubble Sortare și Sortare rapida.

Complexitatea spațială

Sortarea prin inserție nu necesită spațiu suplimentar pentru sortarea elementelor. Complexitatea spațiului este constantă, adică O(1), deoarece se utilizează doar câteva variabile temporare, indiferent de dimensiunea intrării.

Complexitatea timpului

Deoarece sortarea prin inserție iterează câte un element odată, necesită N-1 treceri pentru a sorta N elemente. Pentru fiecare trecere, poate face zero schimbări dacă elementele sunt deja sortate sau poate necesita mai multe schimbări dacă elementele sunt aranjate în ordine descrescătoare.

  • Pentru trecerea 1, schimburile minime necesare sunt zero, iar swapurile maxime necesare sunt 1.
  • Pentru trecerea 2, schimburile minime necesare sunt zero, iar swapurile maxime necesare sunt 2.
  • Pentru trecerea N, schimbul minim necesar este zero, iar swapurile maxime necesare sunt N.
  • Schimbarea minimă este zero, deci cea mai bună complexitate de timp este O(N) pentru repetarea N treceri.
  • Numărul maxim de schimbări este (1+2+3+4+…+N), adică N(N+1)/2, deci cea mai slabă complexitate temporală este O(N^2).

Iată complexitatea temporală importantă a sortării prin inserție:

  • Complexitatea celui mai rău cazO(n^2): Sortarea unui tablou în ordine descrescătoare atunci când trebuie să fie crescătoare este cel mai rău scenariu posibil.
  • Complexitatea celui mai bun caz: O(n): Cel mai bun caz apare atunci când matricea este deja sortată; bucla externă rulează de n ori, în timp ce bucla interioară nu rulează deloc. Există doar n comparații, deci complexitatea este liniară.
  • Complexitatea medie a cazului: O(n^2): Aceasta se întâmplă atunci când elementele tabloului apar într-o ordine amestecată, care nu este nici crescătoare, nici descendentă.

Întrebări frecvente

Alegeți sortarea prin inserție pentru matrice mici, date aproape sortate sau inserții în flux continuu în care elemente noi sosesc după o sortare inițială. Costul său suplimentar constant redus și comportamentul adaptiv adesea depășesc algoritmii mai complecși în aceste sarcini de lucru.

Da. Sortarea prin inserție este stabilă deoarece nu schimbă niciodată valorile egale, păstrându-le ordinea originală. De asemenea, este in situ deoarece sortează folosind doar matricea de intrare plus un număr mic fix de variabile temporare, oferind un spațiu auxiliar O(1).

Cel mai bun caz este O(n) atunci când intrarea este deja sortată deoarece bucla interioară nu se execută niciodată. Cel mai rău caz, cât și cel mediu sunt ambele O(n^2) atunci când matricea este sortată invers sau amestecată, din cauza deplasării repetate a elementelor spre partea din față a matricei.

Asistenții inteligenți artificiali generează animații pas cu pas și tabele care marchează elementul curent, regiunea sortată și indicatorul de comparație pentru fiecare trecere. Această vizualizare îi ajută pe cursanți tracschimbă elementele e, identifică erorile de tip off-by-one și confirmă că prefixul sortat crește cu un element la fiecare iterație externă.

Da. Selectoarele bazate pe inteligență artificială inspectează dimensiunea, distribuția și presortarea matricelor, apoi direcționează intrările mici sau aproape sortate către sortarea prin inserție, în timp ce intrările aleatorii mai mari sunt direcționate către sortarea rapidă sau sortarea prin îmbinare. Algoritmii hibrizi, cum ar fi Timsort, aplică deja această idee în partițiile lor interne.

Sortarea prin inserție construiește regiunea sortată prin inserarea fiecărui element nou în poziția corectă, în timp ce sortarea prin selecție găsește în mod repetat minimul regiunii nesortate și îl adaugă. Sortarea prin inserție este adaptivă și stabilă; sortarea prin selecție standard nu este adaptivă și nu este stabilă în mod natural.

Rezumați această postare cu: