Se afișează postările cu eticheta sortare prin insertie. Afișați toate postările
Se afișează postările cu eticheta sortare prin insertie. Afișați toate postările

sâmbătă, 21 decembrie 2013

Insertion sort - algortim de sortare(partea II)

     Am revenit si cu partea a doua din micul nostru tutorial despre algortimul de insertion sort. In aceasta partea va voi prezenta si descrie implementatia algortimului in alte doua limbaje de programare, Python si PHP. Pe finalul acestei parti va propun sa ne detasam de modul clasic de invatare si sa abordam problema mai neconventional.

Implementatia in Python 
for i in range(1, n): 
    value = v[i]
    j = i - 1
    while j >= 0
        if value < v[j]: 
            v[j + 1] = v[j] 
            v[j] = value
            j = j - 1 
        else :
            break

Modul de functionare este aproape identic cu cel al programului scris in C, deci vom explica doar particularitatile limbajului Python in detaliu.

Pe linia 1 avem o bucla for ce spune ca variabila i va lua valori de la 1 pana la n. n reprezinta numarul de elemente ale listei. Atentie! i nu va lua valoarea n, valoarea maxima pe care o va lua i este n-1. Aminteste-ti, din nou, ca listele sunt indexate de la 0.

Pe linia 2 initializam variabila value cu valoarea elementului de indice i din lista v.

Pe linia 3 initializam variabila j cu valoarea i - 1. Iti este familiara aceasta secventa? Acelasi lucru l-am facut si in pareta anterioara a tutorialului, doar ca atunci am initializat acea variabila prin for.

Pe linia 4 aveam o bucla while ce va rula pana cand variabila de ciclare j va lua valoarea 0.

Pe linia 5  avem o operatie decizionala dictata de conditia ca elementul de indice j sa fie mai mare ca variabila value in care avem stocata valoarea elementului curent.

Pe liniile 6 si 7 inversam pozitiile celor doua elemente din lista, respectiv value cu v[j]. Atentie! Dupa cum am mentionat si in partea I, v[j] este elementul din stanga celui curent, deci v[j] apartine liste sortate.

Pe linia 8 decrementam variabila j, deci scadem 1 din valoarea ei.

Pe linia 10  oprim bucla intrucat am patruns pe ramura else a operatiei conditionale, deci nu mai exista elemente mai mari ca value in lista sortata. Prin urmare, value a ajuns la pozitia destinata.

Implementatia in PHP
for($i = 1; $i < $n; $i++) {
    $value = $array[$i];
    for($j = $i - 1; $j >= 0; $j--) {
        if($value < $array[$j]) {
            $array[$j + 1] = $array[$j];
            $array[$j] = $value;
        }
        else {
            break;
        }
    }
}


Dupa cum, probabil, ati oservat, implementatia in PHP a algortimului este mai mult decat identica cu cea in C - exceptand cateva mici particularitati ale PHP-ului. Consider ca nu mai este necesara descrierea detaliata a codului.

Desigur, am fi putut itera array-ul folosindu-ne de un foreach, dar aceasta miscare s-ar fi sondat cu linii de cod in plus astfel incat sa puteam modifica elemente din array-ul pe care il iteram prin intermediul foreach-ului. Ia aminte ca modificarea elementelor unui array in interiorul buclei foreach poate duce la comportament impredictibil.

Problema: 
Cum am putea evita folosirea constructului break?

Raspuns:
Vom modifica conditia astfel:
for($i = 1; $i < $n; $i++) {
    $value = $array[$i];
    for($j = $i - 1; $j >= 0 && $value < $array[$j]; $j--) {
        $array[$j + 1] = $array[$j];
        $array[$j] = $value;
    }
}

Mult mai elegant, nu-i asa? Practic am renuntat la operatia decizionala, iar cea de a doua bucla exista doar pentru a-l interschimba pe $value cu valorile mai mari decat el din array-ul sortat. Cand nu mai sunt valori mai mari decat $value in array-ul sortat bucla se opreste.

Deci, cum s-ar citi noua conditie? Simplu, atat timp cat $j este mai mare sau egal cu 0 si exista valori mai mari decat $value in partea sortata a array-ului.

Observa ca mi-am adaptat terminologia in functie de limbaj.

Problema 2:
Modifica codul astfel incat sa sorteze un array in ordine descrescatoare.

Raspuns:
Pentru a obtine acest rezultat trebuie sa inlocuim doar un operator, respectiv operatorul <,
$value < $array[$j]
deci vom aveam:
$value > $array[$j]
Conditia noastra se va citi acum astfel: atat timp cat j este mai mare sau egal ca 0 si exista elemente mai mici decat $value. Astfel, $value va interschimba pozitiile cu elementele mai mici decat el din lista sortata(descrescator). Practic, $value va fi mutat spre stanga pana cand nu vor mai fi valori mai mici decat el in array-ul sortat.

O alta modalitate de abordare

   Ce spuneti de acest clip? Vi se pare familiar acest dans?


De asemenea, daca doriti mai mult material de studiu va recomand urmatoarele:



vineri, 20 decembrie 2013

Algoritmul de insertion sort


Insertion sort - algortim de sortare(partea I)


     Algoritmul de insertion sort este, probabil, unul dintre cei mai cunoscuti algortimi de sortare intrucat este usor de invatat, iar stapanirea acestuia este un criteriu obligatoriu ce trebuie indeplinit de oricine vrea sa inteleaga algortimi mai complexi derivati din acesta - precum shell sort despre care vom discuta intr-un alt articol.

   Mi-am propus sa va descriu modul de functionare al algortimului, apoi va voi arata implementatia acestuia in 3 limbaje de programare urmand sa va descriu codul de pe fiecare linie.

Descrierea Algoritmului

   Algoritmul presupune formarea unei liste sortate, apoi compararea fiecarui element din lista principala - adica cea nesortata - cu fiecare element din lista nesortata. In functie de aceste comparatii vom decide unde sa inseram elementul curent astfel incat lista sortata sa ramana in continuare sortata. Algoritmul s-ar putea sa va fie destul de familiar, intrucat este modul natural al oamenilor de a sorta lucrurile. Ganditi-va ca vreti sa plasati o carte intr-un pachet de carti astfel incat acesta sa fie in ordine. Cum procedati? Ei bine, comparati cartea in cauza cu fiecare dintre cele aflate deja in pacahet si o introduceti in locul unde apartine in functie de rezultatul acestor coparatii.

    Sa exemplificam modul de functionare. Considerati lista neordonata de numere:
2, 1, 3, 4
    Vom considera ca lista sortata contine doar elementul 2. Deci, vom incepe sa luam fiecare element incepand cu elementul 1 si le vom compara cu fiecare element din lista sortata adaugandu-l pe baza acestor comparatii in lista sortata.

Deci, comparam elementul 1 cu fiecare din lista sortata:
 2, 1, 3, 4
Cum, deocamdata, lista sortata este compusa doar din elementul 2, il vom compara pe 1 cu 2. 2 este mai mare ca 1, deci ar trebui sa le schimbam pozitiile intre ei astfel:
                                                                           2, 1, 3, 4
                                                                           1, 2, 3, 4
Dupa cum vedeti, elemente 1 si doi si-au schimbat pozitiile intre ele. acum lista noastra ordonata contine elementele: 1, 2. Trecem la urmatorul element, 3, si-l vom compara cu fiecare element din lista ordonata:

                                                                           1, 2, 3, 4
Doi este mai mare ca 3? Nu. Deci, nu mai are sens sa-l comparam pe 3 si cu celelalte elemente din lista ordonata intrucat daca 2 - numarul cel mai mare la acest momenet din lista ordonata - nu este mai mare ca 3, atunci nici 1 nu va fi mai mare ca 3. Asa ca 3 isi pastreaza pozitia. Lista ordonata arata astfel: 1, 2, 3. Trecem la urmatorul element.

                                                                          1, 2, 3, 4

Il vom compara pe 4, pe rand, cu fiecare element din lista ordonata. 3 este mai mare ca 4? Nu. Deci nu mai are sens sa-l comparam si cu celelalte. 4 isi pastreaza pozitia.
Dupa cum puteti vedeam am sortata lista.

Sa luam un alt exemplu:
3, 4, 2, 1

Lista sortata contine elementul 3. Vom compara fiecare element din lista nesortata cu fiecare din lista sortata. 
3, 4, 2, 1
Ia sa vedem. 3 este mai mare decat 4? Nu. Deci, 4 isi pastreaza pozitia. Lista sortata arata acum astfel: 3, 4. Trecem, la urmatorul element:

                                                                          34, 2, 1
Il vom compara pe doi cu fiecare element din lista sortata. 4 este mai mare decat 2? Da. Deci 4 ar trebui sa treaca pe pozitia lui 2 iar doi pe pozitia lui patru:
                                                                         3, 42, 1
                                                                         32, 4, 1
Dupa cum spuneam, il comparam pe doi cu fiecare element din lista sortata, dar a mai ramas 3. Deci, 3 este mai mare ca doi? Categoric da. Deci, 3 ar trebui sa treaca pe pozitia lui 2 si 2 pe pozitia lui 3.
                                                                         324, 1
                                                                        2, 3,  4, 1
L-am comparat pe doi cu fiecare element din lista sortata pana am putut stabili cu exactitate pozitia lui in lista.  Lista noastra sortata ara asa acum: 2, 3, 4. Acum puteam trece la urmatorul element, 1.
                                                                         2, 3, 4, 1

Il vom compara pe 1 cu fiecare element din lista sortata. 4 este mai mare ca 1? Da! deci 4 si 1 ar trebui sa schimbe pozitiile intre ei.
                                                                         2341
                                                                         231, 4
Il comparam pe 1 cu urmatorul element din lista sortata. 3 este mai mare ca 1? Da, da, da. deci 3 si 1 ar trebui sa schimbe pozitiile intre ei.
                                                                         2314
                                                                         21, 3, 4
Il comparam pe 1 cu ultimul element din lista sortata pentru a vedea daca ii mai schimbam pozitia sau daca va rama acolo unde este. 2 este mai mare decat 1? Da. deci 2 si 1 ar trebui sa schimbe pozitiile intre ei.
                                                                        21, 3, 4
                                                                        1, 23, 4

Intr-un final, avem o lista sortata(crescator).

Probabail ca ati remarcat ca aceasta "lista ordonata/sortata" de care tot aduc vorba face parte din lista principala pe care vrem sa o sortam. Este doar un concept abstract folosit pentru a explica mult mai bine modul de functionare al algoritmului.

Implementatia algortimului

   Nu ne mai ramane decat sa implementam acest algortim intr-un limbaj de programare. Din motive obiective il voi implemeneta in 3 limbaje: C, Python si PHP.


Sa incepem cu implementatia in C:
for(i = 0; i < n; i++) {
        currentElement = v[i];
        for(j = i - 1; j >= 0; j--) {
            if(currentElement < v[j]) {
                v[j + 1] = v[j];
                v[j] = currentElement;
            }
            else {
                break;
            }
        }
    }

Pe linia 1 aveam o bucla for ce va duce variabila de ciclare i de la valoarea 1 la n-1. De ce incepem de la 1? Pentru ca primul element al array-ului va reprezenta lista sortata. Aminteste-ti ca array-urile sunt indexate de la 0

Pe linia 2 salvam valoarea aflata in elementul v[i], deci elementul de indice i in variabila currentEelement

Pe linia 3 avem o bucla for in care initializam variabila de ciclare j cu valoarea i-1. Cine este elementul de indice i-1? Exact elementul din spatele celui curent, deci primul element din lista sortata - daca ar fi sa numaram de la stanga la dreapta. Punem conditia ca bucla sa ruleze pana cand j ia(inclusiv) valoarea 0. La fiecare etapa a buclei decrementam variabila j cu o unitate.

Pe linia 4 verificam daca elementul de indice j este mai mare decat elementul curent. Cine este acest element de indice j? Exact, elementul din spatele lui currentEelement. In cazul in care elementul de indice j este mai mare decat currentElement trecem pe ramura de adevar(TRUE) a if-ului.

Pe linia 5 "spunem" ca pozitia j+1 din array va fi ocupata de elementul de pe pozitia j.  Atentie! Cine este elementul de pe pozitia j+1 ? Elementul curent. Deoarece am salvat valoarea elementului curent in variabila currentElement aceasta nu este pierduta.

Pe linia 6 ocupam pozitia j a array-ului cu valoarea salvata in variabila currentElement. Practic, pe aceste doua linii de cod, 5 si 6, am interschimbat pozitia elementului curent cu cea a elementului din lista ordonata ce este mai mare ca acesta. Acest procedeu se va repeta pana cand nu va mai fi niciun element in lista ordonata mai mare decat cel curent.

Pe linia 7 oprim cea de a doua bucla. Intrucat am patruns pe ramura else a if-ului, deci nu mai sunt elemente mai mari decat cel curent in lista ordonata.

Desigur, am fi putut sa evitam utilizarea constructului break prin alterarea conditiei din cea de a doua bucla. Dar am considerat ca ar fi mult mai usor de inteles asa.