Note Complete
Note Complete
Structură
1.0 Obiective
1.1 Introducere în algoritmi
1.2 Proprietă ț ile algoritmului
1.3 Nota ț ii Algoritmice
1.4 Design and development of an algorithm
1.5 Câteva exemple simple
1.6 Summary
1.7 Keywords
1.8 Răspunsuri pentru a- ț i verifica progresul
1.9 Exerci ț ii finale ș i răspunsuri
1. 10 lecturi sugerate
1.0 OBIECTIVE
Un algoritm, numit după matematicianul persan al-Khowarizmi din secolul al nouălea, este
pur ș i simplu un set de reguli folosite pentru a efectua unele calcule, fie manual, fie mai adesea
pe o maș ină Chiar ș i greaca antică a folosit un algoritm care este cunoscut în mod popular ca
Algoritmul lui Euclid pentru calcularea celui mai mare divizor comun (cmmdc) al două numere.
Un algoritm este un instrument pentru rezolvarea unei probleme date. Înainte de a scrie un program pentru a rezolva
problema dată, un programator bun mai întâi proiectează ș i scrie algoritmul corespunzător,
analizează, rafinează de câte ori este necesar ș i ajunge la forma finală „eficientă“
care funcț ionează bine pentru toate datele de intrare valide ș i rezolvă problema în cel mai scurt timp posibil
timp, utilizând un spaț iu minim de memorie.
1
Cerinț a de bază este ca formularea problemei să fie foarte clară
pentru că anumite concepte pot fi clare pentru cineva ș i este posibil să nu fie clare pentru altcineva.
De exemplu, calcularea rădăcinilor unei ecuaț ii cuadratice poate fi clară pentru oamenii care
ș tie despre matematică, dar poate fi neclar pentru cineva care nu este.
Un algoritm bun este ca un cuț it ascuț it - face exact ceea ce este destinat să facă cu o
cantitatea minimă de efort aplicat. Folosirea unui algoritm greș it pentru a rezolva o problemă este ca
încerci să tai un steak cu o ș urubelniț ă. Obț ii un rezultat, dar ai fi cheltuit
mai mult efort decât este necesar.
Introducere
↓
Problemă -- Algoritm -- Calculator Ieș ire
Fiecare algoritm trebuie să îndeplinească anumite proprietăț i. Proprietăț ile variate sau
caracteristicile unui algoritm sunt:
1. Precise ș i neambiguu (Definitate): Un algoritm trebuie să fie simplu, precis
ș i neechivoc, adică nu ar trebui să existe nicio ambiguitate în instrucț iuni
sau afirmaț ii specificate pentru a rezolva o problemă. Fiecare instrucț iune utilizată în
algoritmul trebuie să fie clar ș i neambiguu.
2
2. Gama de intrări: Gama de intrări pentru care algoritmul produce rezultatul dorit
rezultatul ar trebui să fie specificat.
3. Men ț ineț i ordinea: Instruc ț iunile din fiecare pas al algoritmului sunt I
ordinea specificată adică vor fi executate în succesiune (adică una după alta).
instrucț iunile nu pot fi scrise într-o ordine aleatorie.
4. Finite ș i corect: Ei trebuie să rezolve problema într-un număr finit de pa ș i.
ș i produce rezultatul corespunzător. Domeniul de intrare pentru care algoritmul
funcț ionează perfect ar trebui specificat.
5. Încheiere: algoritmul ecac ar trebui să se încheie.
6. Mai există mai multe algoritmi pentru a rezolva o problemă dată ș i viteza de execu ț ie a
each algorithm may be different. (for example, to sort various algorithms bubble
sortare, sortarea prin inserare poate fi utilizată).
7. Un algoritm poate fi reprezentat în mai multe moduri diferite.
8. Algoritmul pentru o problemă dată poate fi bazat pe idei foarte diferite (de exemplu,
to sort several methods exist such as bubble sort, insertion sort, radix sort etc.)
ș i pot avea viteze de execuț ie diferite.
3
1. Declara ț ia problemei.
2. Dezvoltarea unui model matematic
3. Proiectarea algoritmului
4. Implementare
5. Analiza algoritmului pentru complexitatea sa în timp ș i spa ț iu
6. Testarea ș i depanarea programului
7. Documenta ț ie.
1. Declara ț ia problemei.
Înainte de a încerca să rezolvăm o problemă dată, trebuie să în ț elegem precis
declaraț ia algoritmului. Există din nou mai multe modalităț i de a face acest lucru. Putem lista toate
cerin ț e de specifica ț ie a software-ului ș i încearcă să pui mai multe întrebări ș i să ob ț ii
răspunsuri. Acest lucru ne-ar ajuta să înț elegem mai clar problema ș i să eliminăm orice
ambiguitate.
Având înț eles problema, următorul pas este să căutăm un model matematic,
care este cel mai potrivit pentru problema dată. Aceasta este o etapă foarte importantă în ansamblu
procesul de soluț ionare ș i ar trebui acordată o considerabilă atenț ie. De fapt, alegerea
modelul mai are un drum lung de parcurs în procesul de dezvoltare.
Trebuie să ne gândim la
Care model matematic este cel mai potrivit pentru orice problemă dată?
- Există vreun model care a fost deja selectat pentru a rezolva o problemă care
asemănătoare cu cea actuală?
3. Proiectarea algoritmului
4. Implementare
În acest pas, trebuie să fie selectate ș i codificate structuri de date adecvate într-o limbaj ț intă.
Selectarea unei limbi ț intă este un sub-pas foarte important pentru a reduce complexităț ile implicate.
în programare.
În această secț iune, vom folosi o serie de termeni precum complexitate, analiză, eficienț ă.
etc. Toate aceste termeni se referă la performanț a unui program. Sarcina noastră nu poate să se oprească odată ce
scriem algoritmul ș i îl codificăm în, să zicem, C sau C++ sau Java. Ar trebui să ne facem griji cu privire la
cerinț e de spaț iu ș i de timp, de asemenea. De ce? Există mai multe motive pentru aceasta ș i astfel noi
vom începe cu complexitatea temporală.
În termeni simpli, complexitatea temporală a unui program este cantitatea de timp de calculator de care are nevoie pentru a
rulează un program.
4
Complexitatea spaț ială a unui program este cantitatea de memorie necesară pentru a rula un program.
7. Documentaț ie
ALGORITM : gcd(m,n)
//Scop: Găsirea celui mai mare divizor comun al două numere
Acest algoritm calculează PGCD-ul a două numere nenegative ș i diferite de zero
valori acceptate ca parametri.
Două valori non-negative ș i diferite de zero m ș i n
GCD al m ș i n
2. Algoritm pentru a găsi GCD-ul a două numere. (Metoda verificării numerelor întregi consecutive).
5
ALGORITM : cmmdc(m,n)
//Scop: A găsi HCM-ul a două numere
Acest algoritm calculează GCD-ul a două numere non-negative ș i non-zero.
valori acceptate ca parametrii.
Două valori non-negative ș i non-zero m ș i n
CMMDCA dintre m ș i n
ALGORITM : gcd(m,n)
//Scop: A găsi MCD-ul a două numere
Acest algoritm calculează PCM-ul a două numere nenegative ș i diferite de zero
valori acceptate ca parametri.
Două valori non-negative ș i non-zero m ș i n
GCD al m ș i n
Pasul 1: [Dacă unul dintre cele două numere este zero, returnează numărul non-negativ a, GCD-ul]
dacă (m=0) returnează n;
Notă: Aceeaș i problemă poate fi rezolvată în multe moduri (de exemplu, Algoritmul 1, 2 ș i 3).
6
4. Algoritm pentru generarea numerelor prime folosind metoda sitului lui Eratostene. (Pseudo
cod)
ALGORITMUL SIEVE_PRIME(n)
//Scop :Generarea numerelor prime între 2 ș i n
//Description :This algorithm generates prime numbers using sieve method
Un număr întreg pozitiv n>=2
//Output : Prime numbers <=n
Pasul 5 : [Finalizat ]
Ieşire
[Link] pentru a găsi numărul de cifre într-o reprezentare binară a unui dat
număr întreg zecimal
Algoritm : Binar(n)
//Purpose :To count the number of digits in a binary representation of a given
integer zecimal.
//Input :n : un întreg pozitiv zecimal.
7
//Output :Number of digits in a binary representation of a given positive decimal
întreg
Numără 1;
În timp ce ( n > 1)
Numără Numără + 1
n n/2
sfârș it în timp ce
returnează Numărul
Verifică-ț i progresul
1.6 REZUMAT
1.7 KEYWORDS
Algoritm: Este o secvenț ă de instrucț iuni neambigue pentru a rezolva o problemă într-un mod finit.
cantitatea de timp.
Complexitatea timpului: Este timpul necesar pentru a executa un program.
Complexitatea spaț ială: Este cantitatea de memorie necesară pentru a rula un program.
1. 1.1
2. 1.2
8
3.1.5(4thalgoritm)
4. 1.4
1.5 (1stalgoritm
2. 1.5 (1stalgoritm) [ Indiciu : găseș te gcd(12,24) ]
3. 1.5 (3rdalgoritm
4. 1.5 (5thalgoritm)
9
MODULUL-1, UNITATEA 2 ANALIZA EFICIENȚEI ALGORITMULUI
Structură
1.0 Obiective
1.1 Introducere în algoritmi
1.2 Proprietă ț ile algoritmului
1.3 Note algoritmice
1.4 Proiectarea ș i dezvoltarea unui algoritm
1.5 Câteva exemple simple
1.6 Rezumat
1.7 Cuvinte cheie
1.8 Răspunsuri pentru a verifica progresul tău
1.9 Exerci ț ii finale ș i răspunsuri
1. 10 lecturi sugerate
1.0 OBJECTIVES
La sfârș itul acestei unităț i, vei fi capabil să
1.1 INTRODUCERE
Două modalităț i importante de a caracteriza eficacitatea unui algoritm sunt spaț iul său
complexitate ș i complexitate temporală. Complexitatea temporală a unui algoritm se referă la determinarea
o expresie a numărului de paș i necesari ca o funcț ie a dimensiunii problemei. Deoarece
măsurarea numărului de paș i este oarecum grosieră, nu se urmăreș te obț inerea unui număr exact de paș i
numără. În schimb, se încearcă doar să se obț ină limite asimptotice asupra numărului de paș i. Asimptotic
analiza foloseș te notaț ia O (Big Oh). Alte două construcț ii de notaț ie utilizate de
conducătorii de calculatoare în analiza algoritmilor sunt notaț ia Θ (Big Theta) ș i Ω (Big
Notaț ia Omega
10
1.2 Complexitatea spa ț ială
Complexitatea de spaț iu a unui program este cantitatea de memorie care poate fi necesară pentru a rula
un program.
1. Memoria principală a unui computer este o resursă importantă pentru func ț ionarea corectă
executarea unui program. Fără suficientă memorie, fie programul funcț ionează
încet sau s-ar putea să nu funcț ioneze deloc. Prin urmare, cerinț a exactă de memorie pentru o
programul trebuie să fie în avans.
2. Atunci când proiectăm un program, trebuie să ne asigurăm că cerin ț ele de memorie sunt men ț inute la
minimum astfel încât chiar ș i calculatoarele cu memorie mai puț ină să poată executa programul.
3. În zilele noastre, sistemele de operare se ocupă de utilizarea eficientă a memoriei
bazat pe conceptul de memorie virtuală sau legare ș i încărcare dinamică.
Spa ț iu de date
Spaț iul necesar pentru constante, variabile statice, variabile intermediare, dinamice
variabile etc. Acesta nu este altceva decât spaț iul segmentului de date.
•Spa ț iu de stivă
Pentru a stoca adresa de retur, valorile de retur, etc. Pentru a stoca aceste detalii, un segment de stivă
va fi folosit.
{
int a,b,c,avg;
scanf("%d %d%d", a, b, c);
11
avg=(a+b+c)/3;
printf("media este=%d", avg);
}
Deoarece a, b, c ș i avg sunt toate variabile întregi, spaț iul ocupat de ele este
=4*sizeof(int)
=4*2bytes
=8bytes
Spaț iul ocupat de constantul 3 este = 1*2 octeț i.
Prin urmare, spaț iul total este = 8 + 2 = 10 octeț i.
Două moduri importante de a caracteriza eficienț a unui algoritm sunt spaț iul său
complexitatea ș i complexitatea temporală. Complexitatea temporală a unui algoritm se referă la determinarea
o expresie a numărului de paș i necesari ca o funcț ie a dimensiunii problemei. Deoarece
măsura numărului de paș i este oarecum grosolană, nu se urmăreș te obț inerea unui pas exact
număr. În schimb, se încearcă doar obț inerea limitelor asimptotice asupra numărului de paș i. Asimptotic
analiza foloseș te notaț ia O (Big Oh). Alte două constructe de notare folosite de
oamenii de ș tiinț ă computaț ionali în analiza algoritmilor sunt notaț ia Θ (Big Theta) ș i Ω (Big
Notaț ia Omega)
Evaluarea performanț ei unui algoritm se obț ine prin totalizarea numărului de
apariț iile fiecărei operaț iuni atunci când se rulează algoritmul. Performanț a unui
algoritmul este evaluat ca o funcț ie a dimensiunii de intrare n ș i trebuie considerat modulo a
constant multiplicativ.
Următoarele note sunt note utilizate frecvent în analiza performanț ei ș i sunt folosite pentru
caracterizează complexitatea unui algoritm.
Această notare limitează o funcț ie în limite constante. Spunem că f(n) = Θ(g(n)) dacă există
există constante pozitive0,c1ș i2astfel încât la dreapta lui n0valoarea off(n) se află întotdeauna
12
între1g(n) ș i c2g(n) inclusiv.
Θ(g(n)) = {f(n) : există constante pozitive c1,c1, andn0astfel încât 0 ≤ c1g(n) ≤ f(n)
≤c2g(n) pentru toț i n≥n0}
Graficeș te, pentru toate valorile lui n la dreapta lui n0, valoarea off(n) se află la sau deasupra c1g(n)
ș i la sau sub2g(n). Cu alte cuvinte, pentru toț i n ≥ n0f(n) este egal cu g(n) la
într-un factor constant. Spunem că g(n) este o limită asimptotică strânsă pentru f(n).
În terminologia seturilor, f(n) se spune că este un membru al setului Θ(g(n)) de funcț ii. În alte
cuvinte, deoarece O(g(n)) este un set, am putea scrie
f(n)∈Θ(g(n))
f(n) = Θ(g(n))
Din punct de vedere istoric, această notare este "f(n) = Θ(g(n))", deș i ideea că f(n) este egal cu
ceva numit Θ(g(n)) este înș elător.
13
Această notaț ie oferă o limită superioară pentru o funcț ie, în limitele unui factor constant. Noi
writef(n) = O(g(n)) dacă există constante pozitive0ș i astfel încât să fie la dreapta lui n0,
valoarea off(n) se află întotdeauna pe sau sub g(n).
În notaț ia mulț imilor, scriem după cum urmează: Pentru o funcț ie dată g(n), mulț imea funcț iilor
O(g(n)) = {f(n): există constante pozitive c ș i n0astfel încât 0 ≤f(n) ≤c g(n) pentru
toate n≥n0}
Spunem că funcț ia g(n) este o limită superioară asimptotică pentru funcț ia f(n). Folosim
O-notation pentru a oferi o limită superioară unei funcț ii, într-un factor constant.
Grafic, pentru toate valorile lui n la dreapta lui n0, valoarea funcț iei f(n) este pe sau
sub g(n). Scriem f(n) = O(g(n)) pentru a indica că o funcț ie f(n) este un membru al mulț imii
O(g(n)) adică
f(n)∈Ο(g(n))
Observaț i că f(n) = Θ(g(n)) implică f(n) = Ο(g(n)), deoarece notaț ia Θ este o notare mai puternică.
decât notaț ia Ο.
Dacă f(n) ș i g(n) sunt funcț ii definite pe numerele întregi pozitive, atunci f(n) este Ο(g(n)) dacă ș i
numai dacă există ac> 0 ș i an0> 0 astfel încât
14
Notă istorică: Notaț ia a fost introdusă în 1892 de matematicianul german Paul
Bachman.
Această notare oferă o limită inferioară pentru o funcț ie în cadrul unui factor constant. Scriem f(n)
= Ω(g(n)) dacă există constante pozitive0ș i astfel încât să fie la dreapta lui0, valoarea
off(n) minte întotdeauna pe sau deasupra g(n).
În notaț ia mulț imilor, scriem după cum urmează: Pentru o funcț ie dată g(n), mulț imea funcț iilor
Ω(g(n)) = {f(n) : există constante pozitive c ș i n0astfel încât 0 ≤ c g(n) ≤ f(n) pentru
toate n≥n0}
Spunem că funcț ia g(n) este o limită inferioară asimptotică pentru funcț ia f(n).
Complexitatea unui algoritm este o funcț ie g(n) care oferă limita superioară a
numărul de operaț iuni (sau timpul de execuț ie) efectuate de un algoritm atunci când dimensiunea de intrare este n.
15
Complexitate medie
Timpul de execuț ie pentru orice dimensiune de intrare dată va fi numărul mediu de
operaț iuni asupra tuturor instanț elor problemei pentru o dimensiune dată.
1.4.2 Optimalitate
Odată ce complexitatea unui algoritm a fost estimată, apare întrebarea dacă aceasta
un algoritm este optim. Un algoritm pentru o problemă dată este optim dacă complexitatea sa
atinge limita inferioară pentru toate algoritmii care rezolvă această problemă. De exemplu, orice
algoritmul care rezolvă problema „intersecț ia n segmentelor” va fi executat la
cel mai puț in2operaț iunile în cel mai rău caz chiar dacă nu face nimic altceva decât să imprime rezultatul. Acesta este
prescurtat prin a spune că problema are Ω(n2) complexitate. Dacă cineva găseș te un O(n2)
un algoritm care rezolvă această problemă, va fi optim ș i de complexitate Θ(n2).
O problemă este considerată dificilă în mod inerent dacă soluț ia sa necesită resurse semnificative,
indiferent de algoritmul utilizat. Teoria formalizează această intuiț ie, introducând
matematicmodele de calcula studia aceste probleme ș i a cuantifica cantitatea
a resurselor necesare pentru a le rezolva, cum ar fi timpul ș i stocarea. Alte măsuri de complexitate
sunt de asemenea folosite, cum ar fi cantitatea de comunicare (folosită încomunicare
complexitate), numărul de porț iîntr-un circuit (utilizat încomplexitatea circuitului)
ș i numărul
de procesoare (folosite încalcul paralel). One of the roles of computational complexity
teoria este de a determina limitele practice asupra a ceea cecomputers poate ș i nu poate face.
16
Domenii strâns legate în ș tiinț a calculatoarelor teoretice suntanaliza de
algoritmiș iteoria calculabilităț iiO distincț ie cheie între analiza algoritmilor
ș i teoria complexităț ii computaț ionale se ocupă de analizarea
cantitatea de resurse necesare unei anumite algoritm pentru a rezolva o problemă, în timp ce
ultima pune o întrebare mai generală despre toate algoritmii posibili care ar putea fi folosiț i pentru
rezolvă aceeaș i problemă. Mai precis, încearcă să clasifice problemele care pot sau nu pot fi
rezolvat cu resurse corespunzător restricț ionate. La rândul său, impunând restricț ii asupra
resursele disponibile sunt ceea ce distinge complexitatea computaț ională de computabilitate
teoria: teoria de mai sus întreabă ce tip de probleme pot, în principiu, fi rezolvate
algoritmic
1.5.1 Probleme de funcț ie
Aproblemă de funcț ieeste o problemă computaț ională în care un singur rezultat (al unui funcț ie totală)
se a ș teaptă pentru fiecare input, dar output-ul este mai complex decât cel al unui decizie
problemă, adică, nu este doar da sau nu. Exemple notabile includ vânzător călător
problemăș iproblema factorizării întregilor.
Este tentant să credem că noț iunea de probleme de funcț ie este mult mai bogată decât noț iunea
al problemelor de decizie. Totuș i, acesta nu este chiar cazul, deoarece problemele de funcț ie pot fi
reformulează-le ca probleme de decizie. De exemplu, înmulț irea două întregi poate fi
exprimate ca un set de triple (a,b,c) astfel încât relaț ia a×b=cholds. Deciderea
fie că un triplet dat este membru al acestui set corespunde rezolvării problemei de
înmulț irea a două numere.
1.5.2 Măsurarea dimensiunii unei instanț e
Pentru a măsura dificultatea rezolvării unei probleme computaț ionale, cineva ar putea dori să vadă cum
timp mult algoritmul cel mai bun necesită pentru a rezolva problema. Cu toate acestea, timpul de execuț ie
poate, în general, depinde de instanț ă. În special, instanț ele mai mari vor necesita mai mult
timpul necesar pentru a rezolva. Astfel, timpul necesar pentru a rezolva o problemă (sau spaț iul necesar, sau orice
măsura complexită ț ii) este calculată ca o func ț ie a dimensiunii instan ț ei. Aceasta este
de obicei considerată a fi dimensiunea intrării în biț i. Teoria complexităț ii este interesată de modul în care
algoritmii escaladează odată cu creș terea dimensiunii intrării. De exemplu, în problema de a găsi
dacă un graf este conectat, cât mai mult timp durează să rezolvăm o problemă pentru un
grafic cu 2n vârfuri comparativ cu timpul necesar pentru un grafic cu n vârfuri?
Dacă dimensiunea de intrare este n, timpul necesar poate fi exprimat ca o funcț ie de n. Deoarece timpul
luate pe baza unor intrări diferite de aceea ș i dimensiune pot fi diferite, cazul cel mai rău în timp
complexitatea T(n) este definită ca fiind timpul maxim necesar pentru toate intrările de mărime n. Dacă T(n)
este un polinom în n, atunci algoritmul este spus a fi unpolinom
[Link] lui Cobhamspune că o problemă poate fi rezolvată cu o cantitate fezabilă
17
de resurse dacă admite un algoritm de timp polinomial.
Pentru j 0 la n-1 fă
C[I,j] 0
Pentru k 0 la n-1 fă
C[I,j] c[I,j]+a[I,k]+b[k,j]
Returnează c
n1n1n1
Complexitatea temporala a acestui algoritm este data de M(n)= 1 =n3
i =0j =0k =0
Algorithm : uniquelement(a[].n)
18
Pentru i i+1 până la n-1 fă
Dacă(a[i]=a[j])
Returnaț i 0;
Sfârș it dacă
Returnează 1;
n -2n -1
Eficienț ă în cel mai rău caz : ∑ ∑1 = n(n−1) / 2<= n2
eu
=0j =e u +1
T(n)€O(n2)
Cea mai bună eficienț ă: dacă a[0]=a[1] atunci operaț ia de bază va fi executată o singură dată.
Verifică-ț i progresul
SUMMARY:
Complexitatea spaț ială: Complexitatea spaț ială a unui program este cantitatea de memorie care poate
1.5 KEYWORDS
Operaț iune de bază – o operaț iune care este executată de mai multe ori în program
(partea logică). De obicei, prezentă în cea mai interioară buclă (parte) a algoritmului/programului.
19
1.6 RASPUNSURI PENTRU A VERIFICA PROGRESUL TĂU
1. 1.2
2. 1.3
3. 1.4
4. 1.6
1.7 EXERCI ȚII Ș I RĂSPUNSURI LA SFÂR Ș ITUL UNITĂ ȚII
VEZI
1. 1.4
2. 1.3
1.8LECTURI SUGERATE
1. Introducere în proiectarea ș i analiza algoritmilor de Anany Levitin
2. Analiza ș i designul algoritmilor cu C/C++ - 3rdediț ie de Prof. Nandagopalan
3. Analiza ș i proiectarea algoritmilor de către Padma Reddy
20
MODULE-1,UNIT 3 ALGORITMI ANALIZĂ ȘI SOLUȚIONARE
RECURRENTE
Structură
1.0 Obiective
1.1 Analizând structurile de control
1.2 Folosind un barometru
2.0 OBIECTIVE
La sfârș itul acestei unităț i vei fi capabil să
•Rezolvarea problemelor de încărcare a containerelor ș i a problemei rucsacului.
Găsi ț i cele mai scurte căi folosind algoritmul lui Prim ș i algoritmul lui Kruskal.
2.1 INTRODUCERE
Un instrument esenț ial pentru a proiecta un algoritm eficient ș i adecvat este 'Analiza de
Algoritmi. Nu există o formulă magică, este pur ș i simplu o chestiune de judecată, intuiț ie ș i
experienț ă. Totuș i, acestea sunt câteva tehnici de bază care sunt adesea utile, cum ar fi
ș tiind cum să te ocupi de structurile de control ș i
ecuaț ii recursive.
Analiza structurilor de control: În cele din urmă, analiza algoritmilor decurge din interior
ieș ire. Determinaț i mai întâi timpul necesar instrucț iunilor individuale, apoi combinaț i
21
aceste tainuri conform sistemelor de control care combină instrucț iunile în
program.
Fie P1 ș i P2 două fragmente ale unui algoritm. Ele pot fi o singură instrucț iune. Ele
pot fi instrucț iuni simple sau sub-algoritmi complicaț i. Să fie t1 ș i t2 timpii
luate de P1 ș i P2. t1 ș i t2 pot depinde de diferite parametrii, cum ar fi instanț a
dimensiune. Regula de secvenț iere spune că timpul necesar pentru a calcula „P1 ș i P2” este pur ș i simplu t1
+ t2. Conform regulii maxime, acest timp este în q(max(t1, t2)). În ciuda simplităț ii sale, aplicarea
această regulă este uneori mai puț in evidentă decât ar putea părea. Ar putea să se întâmple ca unul dintre
parametrii care controlează t2 depind de rezultatele calculului efectuat P1.
Ele sunt cele mai uș oare bucle de analizat. Pentru i 1 până la m fac P(i) Printr-o convenț ie pe care o vom adopta:
m=0 înseamnă că P(i) nu este executat deloc, (nu este o eroare). P(i) ar putea depinde de dimensiune. De
Desigur, cel mai simplu caz este atunci când nu o face. Să fie t timpul necesar pentru a calcula P(i) ș i
timpul total necesar este l=mt. De obicei, această abordare este adecvată, dar există un potenț ial
pitfall: We didn’t consider the time for the “loop control”. After all our for loops is
o abreviere pentru ceva de genul următor pentru bucla while.
eu 1
în timp ce i <= m face
P(i)
eu i + 1
În cele mai proaste situaț ii, este rezonabil să se considere testul i £ m la cost unitar ș i acelaș i
lucru cu instrucț iunile i ¬i + 1 ș i operaț iile de secvenț iere „mergi la” implicite în
bucle while. Să fie „c” limita superioară a timpului necesar pentru fiecare dintre operaț ii:
l <= c pentru i ¬1
+ (m+1)c teste i £ m
+ execuț ia mt a P(i)
+ execuț ie mc a i i + 1
+ operaț iunile de secvenț iere mc
l <= (t+3c)m+2c
Acest timp este clar limitat inferior de mt. Dacă c este neglijabil comparativ cu t, anteriorul nostru
estimarea că l este aproximativ egal cu mt este justificată. Analiza buclei for este mai
interesant când timpul t(i) necesar pentru P(i) variază ca o funcț ie de I ș i/sau de dimensiune
n.
Aș adar: pentru i 1 până la m face P(i) care durează un timp dat de, t(i) (ignorând timpul necesar de către
controlul buclei).
22
Algoritm matmul(a[0…n-1],b[0..n-1])
matrice n pe n
matrice c=ab
C[I,j] 0
C[I,j] c[I,j]+a[I,k]+b[k,j]
Returnează c
n1n1n1
Complexitatea temporală a acestui algoritm este dată de M(n) = 1 €θ(n3)
=0j
eu =0k =0
Analiza algoritmilor recursivi este destul de simplă până la un anumit punct. Simplu
inspecț ia algoritmului dă adesea naș tere unei ecuaț ii de recurenț ă care "mimează"
fluxul de control în algoritm. Tehnici generale despre cum să rezolvi sau cum să transformi
ecuaț ia în ecuaț ii mai simple non-recursive va fi analizată mai târziu.
Aceste două tipuri de bucle sunt de obicei mai greu de analizat decât buclele "for" deoarece există
nu există o modalitate a priori evidentă de a ș ti de câte ori va trebui să facem turul buclei.
Tehnica standard pentru analizarea acestor bucle este de a găsi o funcț ie a variabilelor
implicat unde valoarea scade de fiecare dată când se învârte. Pentru a determina de câte ori
buclele se repetă, însă trebuie să înț elegem mai bine cum se valorizează această funcț ie
scade. O abordare alternativă a analizei buclelor „while” constă în a trata
îi ca algoritmi recursivi. Ilustrăm ambele tehnici cu acelaș i exemplu,
analiza buclelor "repeat" se desfăș oară în mod similar.
23
{
s=0.0;
pentru I=1 până la n face
s= s+a[I];
returnează s;
}
Instan ț ele problemei pentru acest algoritm sunt caracterizate prin n,
numărul de elemente care trebuie sumate. Spaț iul necesar d de ‘n’ este unul
cuvânt, deoarece este de tip întreagă.
Spa ț iul necesar pentru 'a’a este spa ț iul necesar pentru variabile de tip
array de numere cu puncte flotante.
•Aceasta este de cel pu ț in 'n' cuvinte, deoarece 'a' trebuie să fie suficient de mare pentru a con ț ine 'n'
elemente de adunat.
•A ș adar, ob ț inem S sum(n)>=(n+s)
[ n pentru a[], unul fiecare pentru n, I a & s]
Complexitatea Temporală:
Declaraț ie interactivă cum ar fi pentru, cât timp & repetă-până Control parț ial al
declaraț ie.
Algoritm:
Algoritm sum(a,n)
{
s = 0.0;
24
count = count + 1;
pentru I=1 până la n face
{
count = count + 1;
s=s+a[I];
count=count+1;
}
count=count+1;
count=count+1;
returneaza s;
}
Total 2n+3
•Majoritatea timpului, analiza cazului mediu este efectuată sub mai mult sau mai pu ț in
o presupunere realistă că toate instanț ele de orice dimensiune sunt la fel de probabile.
•Pentru problemele de sortare, este simplu de presupus că toate elementele care trebuie să fie
sortate sunt distincte.
•Să presupunem că avem ‘n’ elemente distincte de sortat prin inser ț ie ș i toate n!
permutările acestor elemente sunt la fel de probabile.
25
•Pentru a determina timpul mediu necesar algoritmului, am putea adăuga
timpurile necesare pentru a sorta fiecare dintre permutările posibile, apoi împărț iț i la n!
răspunsul astfel obț inut.
O abordare alternativă, mai u ș oară în acest caz, este să analizăm direct timpul.
cerut de algoritm, raț ionând probabilistic pe măsură ce avansăm.
•Pentru orice I,2 I n, considera sub-array-ul, T[1….i].
Rangul par ț ial al T[I] este definit ca pozi ț ia pe care ar ocupa-o dacă sub
array-urile au fost sortate.
•De exemplu, rangul par ț ial al T[4] în [3,6,2,5,1,7,4] este 3 deoarece T[1….4]
o dată sortat este [2,3,5,6].
•Clar că rangul par ț ial al T[I] nu depinde de ordinea elementului în
•Subarray T[1…I-1].
Analiză
Cazul cel mai bun: Această analiză impune restricț ii asupra inputului, cu excepț ia dimensiunii. Rezultând în cele mai rapide.
timp de execuț ie posibil
Cazul cel mai rău: Această analiză impune constrângeri asupra inputului, în afară de mărime. Rezultând în viteze mai rapide.
timp de execuț ie posibil
Cazul mediu: Acest tip de analiză rezultă în timpul mediu de execuț ie pentru fiecare tip de
input.
Complexitate: Complexitatea se referă la rata la care timpul de stocare cre ș te ca o func ț ie
dimensiunea problemei
Analiza asimptotică: Exprimarea complexităț ii în termeni de relaț ia sa cu cunoaș terea
funcț ie. Această analiză de tip se numeș te analiză asimptotică.
Notaț ie asimptotică:
Mari 'oh': funcț ia f(n)=O(g(n)) dacă ș i numai dacă există constante pozitive c ș i n0 astfel încât
f(n)≤c*g(n) pentru toate n, n ≥ no.
Omega: funcț ia f(n)=Ω(g(n)) dacă ș i numai dacă există constante pozitive c ș i n0 astfel încât
f(n) ≥ c*g(n) pentru toate n, n ≥ no.
Theta: funcț ia f(n) = ө(g(n)) dacă ș i numai dacă există constante pozitive c1, c2 ș i n0 astfel încât
c1 g(n) ≤ f(n) ≤ c2 g(n) pentru toate n, n ≥ no.
1.6 Analiza amortizată
Îninformaticăanaliza amortizată este o metodă deanalizând algoritmiică
consideră întreaga secvenț ă de operaț iuni ale programului. Permite stabilirea
al unei limite de caz cel mai rău pentru performanț a unui algoritm, indiferent de intrări, prin
privind toate operaț iunile. La baza metodei se află ideea că, în timp ce anumite
operaț iunile pot fi extrem de costisitoare în resurse, ele nu pot avea loc la un nivel suficient de ridicat
frecvenț a de a împovăra întregul program din cauza numărului de operaț iuni mai puț in costisitoare
vor depăș i cu mult numărul celor costisitori pe termen lung, "răsplătind" programul pe o
numărul de iteraț ii. Este deosebit de util deoarece garantează cazurile cele mai proaste
performanț ă în timp ce ia în considerare întregul set de operaț ii dintr-un algoritm.
Există în general trei metode pentru a efectua analiza amortizată: agregatul
metoda, metoda contabilă ș i metoda potenț ială. Toate acestea oferă aceeaș i
răspunsuri, iar diferenț a lor de utilizare este în principal circumstanț ială ș i datorată individualităț ii
preferinț ă.
26
. Analiza agregată determină limita superioară T(n) asupra costului total al unei
secvenț a operaț iunilor, apoi calculează costul mediu ca T(n) / n.
. Themetodă contabilă determina costul individual al fiecărei opera ț iuni,
combinând timpul său de execuț ie imediat ș i influenț a sa asupra timpului de rulare al
opera ț iuni viitoare. De obicei, multe opera ț iuni de scurtă durată acumulează o "datorie" de
o stare nefavorabilă în mici creș teri, în timp ce operaț iunile rare de lungă durată o scad
drastic
. Themetodă potenț ialăeste ca metoda contabilităț ii, dar supraîncărci operaț iunile
devreme pentru a compensa subfacturările ulterioare.
Timpul amortizat pe operaț iune este limita de timp în cel mai rău caz pentru o serie de n operaț iuni.
împărț it la n. Timpul amortizat pe operaț iune este astfel
O(3n) /n= O(n) /n= O(1).
1.7 Recursie:
27
Recursia poate fi utilizată pentru calcule repetitive în care fiecare acț iune este declarată
în ceea ce priveș te rezultatul anterior. Există două condiț ii care trebuie să fie îndeplinite de orice
procedură recursivă.
De fiecare dată când o func ț ie se apelează singură, ar trebui să se apropie de solu ț ie.
2. Trebuie să existe un criteriu de decizie pentru oprirea procesului.
În luarea deciziei dacă să scrii un algoritm într-o formă recursivă sau non-recursivă
form, este întotdeauna recomandabil să se considere o structură de arbore pentru problemă. Dacă structura este
simplu atunci foloseș te forma non-recursivă. Dacă copacul pare destul de des, cu puț ină duplicare
al sarcinilor, atunci recursia este potrivită.
Algoritmul de recursie pentru găsirea factorialului unui număr este dat mai jos,
Algoritm: factorial-recursiv
n, numărul a cărui factorial trebuie găsit.
f, factorialul lui n
Metodă: dacă(n=0)
f=1
altfel
f=factorial(n-1) * n
dacă sfârș it
algoritmul se încheie.
3. Restaurează cele mai recent salvate parametri, variabila locală ș i adresa de întoarcere ș i
mergi la cea mai recentă adresă de retur.
28
1.7.2 Itera ț ie vs Recursie:
Recursia este o abordare de sus în jos pentru rezolvarea problemelor. Aceasta împarte problema în bucăț i.
sau selectează un pas cheie, amânând restul.
Iteraț ia este mai degrabă o abordare de jos în sus. Aceasta începe cu ceea ce este cunoscut ș i din aceasta
construieș te soluț ia pas cu pas. Funcț ia iterativă foloseș te evident un timp care este
O(n) în timp ce funcț ia recursivă are o complexitate de timp exponenț ială.
Este întotdeauna adevărat că recursia poate fi înlocuită de iteraț ie ș i stive. De asemenea, este adevărat că
stiva poate fi înlocuită de un program recursiv fără stivă.
29
1.7.4 SOLU ț IONAREA RECUREN ț ELOR :-( Se întâmplă din nou (sau) repetat)
•Ultimul pas indispensabil atunci când analizezi un algoritm este adesea să rezolvi o
ecuaț ie de recurenț ă.
•Cu pu ț ină experien ț ă ș i inten ț ie, majoritatea recuren ț elor pot fi rezolvate prin
ghicire inteligentă
•Cu toate acestea, există o tehnică puternică care poate fi utilizată pentru a rezolva anumite
clase de recurenț ă aproape automat.
•Acesta este un subiect principal al acestei sec ț iuni, tehnica ecua ț iei caracteristice.
Rădăcinile sunt,
-(-1) ± √((-1)² + 4)
x = ------------------------
2
1 ±√ (1 + 4)
= ----------------
2
1 ± √5
= ----------
2
30
1+√5 1 - √5
r1= --------- și r2= ---------
2 2
C1= -C2
1 - √5 1 - √5
C2--------- ---------
- = 1
2 2
1 – √5 – 1 – √5
C2--------------------- = 1
2
-C2* 2√5
-------------- = 1
2
− √5C2= 1
Astfel,
n n
1 1 + √5 -1 1 - √5
fn= ---- --------- + ---- --------
√5 2 √5 2
n n
1 1 + √5 1 - √5
= ------------- - ---------
31
√5 2 2
3. Recursie inomogenă :
Exemplu(1):
Consideraț i recurenț a,
tn- 2tn-1= 3n (A)
Soluț ia generală,
tn= C1r1n+ C2r2n
tn= C12n+ C23n (1)
32
C1+ C2= t0
C1+ 3 = t0
C1= t0– 3
4. Schimbare de variabile:
* Uneori este posibil să rezolvăm recursiuni mai complicate făcând o
schimbarea variabilei.
* În exemplul următor, scriem T(n) pentru termenul unei recursii generale.
ș i tipentru termenul unei noi recursi obț inute din prima printr-o schimbare de
variabilă.
Exemplu: (1)
Consideraț i recurenț a,
1 , dacă n=1
T(n) =
3T(n/2) + n, dacă 'n' este o putere a lui 2, n>1
33
1
T(n) =
3T(n/2) + n
În acest caz,
b = 2, p(n) = 1, degree = 0
Rădăcinile sunt, r1 = 3, r2 = 2.
Ecuaț ia generală,
tn= C1r1eu+ C2r2i
sub. r1& r2: tn= 3nC1+ C22n
tn= C13eu+ C22eu
Folosim faptul că, T(2eu) = teu& astfel T(n) = tlogn când n= 2eua obț ine
T(n) = C13log n+2 C2. 2log n 2
T(n) = C1. nlog 32+ C2.n [i = logn]
Când 'n' este o putere a lui 2, este suficient să concluzionăm că,
Verifică-ț i progresul
34
SUMMARY:
Analiza structurilor de control: În cele din urmă, analiza algoritmilor progresează din interior
ieș ire. Determinaț i mai întâi timpul necesar instrucț iunilor individuale, apoi combinaț i
aceste tinte conform sistemelor de control care combină instrucț iunile în
program.
Recursia poate fi folosită pentru calcule repetitive în care fiecare acț iune este exprimată în termeni
rezultatul anterior.
Rezolvarea recurenț elor folosind următorii paș i: Calculează primele valori ale
recidivă. Caută regularitate. Ghiceș te o formă generală potrivită ș i, în final, dovedeș te prin
inducț ia matematică (poate inducț ie constructivă).
1.7 KEYWORDS
1. Simbolurile mari 'oh', Omega ș i Theta ale notării asimptotice.
1. 1.1
2. 1.5
3. 1.7
4. 1.7
1.7 EXERCI ȚII Ș I RĂSPUNSURI LA FINALUL UNITĂ ȚII
1.9SUGGESTED READINGS
1. Introducere în proiectarea ș i analiza algoritmilor de Anany Levitin
2. Analiza ș i proiectarea algoritmilor cu C/C++ - 3rdediț ie de prof. Nandagopalan
3. Analiza ș i proiectarea algoritmilor de Padma Reddy
35
MODULUL-1, UNITATEA 4 CĂUTARE Ș I SORTARE
Structură
1.0 Obiective
1.1 Algoritmi de căutare
Căutare liniară
Căutare binară
1.2 sorting
Sortare prin selec ț ie
Sortare prin inser ț ie
Sortare prin bule
1.3 Summary
1.4 Keywords
1.5 Răspunsuri pentru a- ț i verifica progresul
1.6 Exerci ț ii ș i răspunsuri la sfâr ș itul unită ț ii
1.7 Suggested readings
3.0 OBIECTIVE
La sfârș itul acestei unităț i vei fi capabil să
În cel mai rău caz, articolul nu este găsit sau articolul căutat este ultimul (nth) element.
{"text":"Pentru ambele situaț ii, trebuie să examinăm toate cele n elemente ale array-ului, astfel că ordinul de magnitudine"}
36
complexitatea căutării secvenț iale este n. adică, O(n). Timpul de execuț ie pentru aceasta
algoritmul este proporț ional cu n, adică algoritmul se execută în timp liniar.
căutare eș uată
algoritmul se încheie.
Metoda de căutare binară este, de asemenea, o metodă relativ simplă. Pentru această metodă este
este necesar să aveț i vectorul într-o ordine alfabetică sau numeric crescătoare. O căutare
pentru un element particular cu X seamănă cu căutarea unui cuvânt în dicț ionar. The
aproximativ mijlocul intrării este localizat ș i valoarea sa cheie este examinată. Dacă valoarea mijlocie este
mai mare decât X, atunci lista este tăiată la (mid-1)thlocaț ie. Acum lista devine
reducere la jumătate din lista originală. Intrarea din mijloc a listei reduse pe stânga este examinată într-un
mod similar. Această procedură este repetată până când articolul este găsit sau lista nu mai are elemente.
elemente. Pe de altă parte, dacă valoarea medie este mai mică decât X, atunci lista este tăiată
la (mid+1)thlocaț ie. Intrarea din mijloc a listei reduse la dreapta este examinată ș i
procedura se continuă până când cheia dorită este găsită sau intervalul de căutare este epuizat.
37
dacă(k<a[mid])
high=mid
altfel
low=mid
dacă se termină
}
în timp ce sfârș it
dacă(k=A[low])
{
căutare reuș ită
scrie(k este la locaț ia joasă)
ieș ire();
}
altfel
scriere (căutare nereuș ită);
dacă sfârș it;
algoritmul se încheie.
1.2 Sorting
Mai multe algoritmi sunt prezentaț i, inclusiv sortarea prin inserț ie, sortarea shell ș i sortarea rapidă.
Sortarea prin inserț ie este cea mai simplă metodă ș i nu necesită stocare suplimentară.
Sortarea Shell este o simplă modificare care îmbunătăț eș te semnificativ performanț a.
Sortarea prin selecț ie este printre cele mai simple tehnici de sortare ș i funcț ionează foarte bine pentru seturi mici.
fiș iere. În plus, în ciuda evidentei sale „abordări naive”, sortarea prin selecț ie are o destul de
aplicaț ie importantă deoarece fiecare element este de fapt mutat cel mult o dată, sortarea secț ională este o
metoda aleasă pentru sortarea fiș ierelor cu obiecte foarte mari (înregistrări) ș i chei mici.
Iată un exemplu pas cu pas pentru a ilustra algoritmul sortării prin selecț ie utilizând numere:
Array original:
6354927
1-a trecere -> 2 3 5 4 9 6 7 (2 ș i 6 au fost schimbate)
2nd pass -> 2 3 4 5 9 6 7 (4 and 5 were swapped)
a treia trecere -> 2 3 4 5 6 9 7 (6 ș i 9 au fost schimbate)
a 4-a trecere -> 2 3 4 5 6 7 9 (7 ș i 9 au fost interschimbate)
A cincea trecere -> 2 3 4 5 6 7 9 (fără schimbare)
al 6-lea pas -> 2 3 4 5 6 7 9 (fără schimb)
38
Notă: Au fost 7 chei în listă ș i, prin urmare, au fost necesare 6 treceri. Cu toate acestea, doar 4
schimburile au avut loc.
pentru i← 1 ton-1 fă
minj←i;
minx← A[i]
pentru j ← i + 1 până la n face
Dacă A[j] < min x atunci
minj←j
minx← A[j]
A[minj] ← A[i]
A[i] ← minx
Cea mai proastă situaț ie apare dacă tabloul este deja sortat în ordine descrescătoare. Totuș i,
timpul necesar algoritmului de sortare prin selecț ie nu este foarte sensibil la ordinea originală a
array-ul care trebuie sortat: testul "ifA[j] < min x" este executat exact acelaș i număr de
timpuri în fiecare caz. Variaț ia în timp este doar din cauza numărului de ori în care apare "atunci"
partea (adică, minj←j; minx←A[j] a acestui test sunt executate.
Sortarea prin selecț ie îș i petrece cea mai mare parte a timpului încercând să găsească elementul minim în
partea „nesortată” a array-ului. Arată clar similaritatea dintre sortarea prin selecț ie ș i
Sortarea prin bule. Sortarea prin bule "selectează" elementele maxime rămase la fiecare etapă, dar
iască ceva efort pentru a impune o ordine părț ii "nesortate" a tabloului. Sortarea prin selecț ie este
cvadratic atât în cel mai rău, cât ș i în cazul mediu, ș i nu necesită memorie suplimentară.
39
Pentru fiecare ifrom 1 ton - 1, există un schimb ș i n-comparări, deci există un total
exchange-uri ofn-1 ș i (n-1) + (n-2) + . . . + 2 + 1 =n(n-1)/2 comparaț ii. Aceste
observaț iile sunt valabile indiferent de datele de intrare. În cel mai rău caz, aceasta ar putea fi
cadratic, dar în cazul mediu, această cantitate este O(nlogn).
Dacă primele câteva obiecte sunt deja sortate, un obiect nesortat poate fi inserat în cele sortate
setat în locul corespunzător. Acesta se numeș te sortare prin inserț ie. Un algoritm consideră elementele unul
la un moment dat, introducând fiecare în locul său potrivit printre cei deja consideraț i (păstrând
le sortate). Sortarea prin inserț ie este un exemplu de algoritm incremental; construieș te
secvenț ă sortată, un număr deodată. Acesta este poate cel mai simplu exemplu al
tehnica de inserț ie incrementală, unde construim o structură complicată pe n elemente prin
mai întâi construind-o pe n − 1 articole ș i apoi făcând modificările necesare pentru a remedia lucrurile
adăugarea ultimului element. Secvenț ele date sunt de obicei stocate în tableau. De asemenea, ne referim la
numere ca chei. Împreună cu fiecare cheie poate exista informaț ii suplimentare, cunoscute ca sateliț i
date. [Reț ineț i că "datele satelit" nu provin neapărat din satelit!]
Reț ineț i că, în orice moment, cărț ile ț inute în mâna stângă sunt sortate, iar aceste cărț i au fost
iniț ial cărț ile de sus ale grămezii de pe masă.
Pseudo cod
SORTARE_PENTRU_INSERARE (A)
40
[Link] ← 2LAlength[A]FACI
2. cheia ←A[j]
Citeș te figura linie cu linie. Elementele din stânga lui A[j] care sunt mai mari decât A[j] se mută
o poziț ie spre dreapta, iar A[j] se mută în poziț ia evacuată.
Analiză
Întrucât timpul de execuț ie al unui algoritm pe o anumită intrare este numărul de paș i
executat, trebuie să definim "pas" independent de maș ină. Spunem că o afirmaț ie care
îi iaeupaș ii de executat ș i timpii executaț i contribuieeuîn timpul total de rulare al
algoritmul. Pentru a calcula timpul de execuț ie, T(n), sumăm produsele costului ș i
coloana timp [vezi CLRS pagina 26]. Adică, timpul de execuț ie al algoritmului este suma
timpilor de execuț ie pentru fiecare declaraț ie executată. Aș adar, avem
În ecuaț ia de mai sus, am presupus căjfii numărul de ori în care bucla while (în linia
5) este executat pentru acel vârf de j. Observaț i că valoarea lui j variază de la 2 la (n− 1). Avem
41
T(n) = c1n+c2(n− 1) +c4(n− 1) +c5∑2 ≤j≤ n(tj) + c6∑2 ≤j≤ n(tj− 1)
+c7∑2 ≤j≤ n(tj− 1) +c8(n− 1) Ecuaț ia (1)
Caz ideal
Cel mai bun caz apare dacă array-ul este deja sortat. Pentru fiecare j = 2, 3, ..., n, găsim
thatA[i] este mai mic sau egal cu cheia când i are valoarea iniț ială de (j− 1). Cu alte cuvinte,
când i=j−1, găseș te întotdeauna cheia A[i] la prima rulare a buclei WHILE.
Prin urmare,j= 1 pentru j= 2, 3, ..., n iar timpul de execuț ie în cel mai bun caz poate fi calculat folosind
ecuaț ia (1) astfel:
T(n) = c1n+c2(n− 1) +c4(n− 1) +c5∑2 ≤j≤ n(1) +c6∑2 ≤j≤ n(1 − 1) +c7∑2 ≤j≤ n(1
− 1) +c8(n− 1)
Linia de bază aici este că bucla while de pe linia 5 a fost executată o singură dată pentru fiecare j. Aceasta
ce se întâmplă dacă arrayA este deja sortat.
T(n) = an + b = O(n)
Worst-Case
Cel mai rău caz apare dacă tabloul este sortat în ordine inversă, adică în ordine descrescătoare. În
în ordinea inversă, întotdeauna descoperim că A[i] este mai mare decât cheia în testul buclei while.
Aș adar, trebuie să comparăm fiecare element A[j] cu fiecare element din întregul sortat
subarrayA[1 ..j− 1] ș i sotj=jforj= 2, 3, ...,n. Echivalent, putem spune că, deoarece
bucle while se încheie deoarece ajunge la 0, există un test suplimentar după (j− 1) teste.
Prin urmare,j=jforj= 2, 3, ..., n iar timpul de execuț ie în cel mai prost caz poate fi calculat folosind
ecuaț ia (1) după cum urmează:
42
T(n) = c1n+c2(n− 1) +c4(n− 1) +c5∑2 ≤j≤ n[n(n+1)/2 + 1]
+c6∑2 ≤j≤ n[n(n− 1)/2] +c7∑2 ≤j≤ n [n(n− 1)/2] +c8(n− 1)
Timpul de execuț ie poate fi exprimat ca (an2+bn+c) pentru constantele a, b ș i c care din nou
depinde de declaraț ia costsceuPrin urmare, T(n) este o funcț ie quadratică de n.
Aici, ideea principală este că cazul cel mai rău se produce atunci când linia 5 este executată de j ori pentru fiecare j.
Aceasta se poate întâmpla dacă arrayA începe în ordine inversă
De obicei ne concentrăm pe găsirea timpului de rulare în cel mai rău caz: cel mai lung timp de rulare
pentru orice dimensiune a intrării sizen. Motivele pentru această alegere sunt următoarele:
Timpul de execu ț ie în cel mai rău caz oferă o limită superioară garantată asupra timpului de execu ț ie
43
În medie, cheia în A[j] este mai mică decât jumătate din elementele în A[1 ..j− 1] ș i este mai mare
decât cealaltă jumătate. Aceasta implică că, în medie, bucla while trebuie să caute până la jumătate.
subvectorul sortat A[1 ..j− 1] pentru a decide unde să aș eze cheia. Aceasta înseamnă căj=j/2.
Deș i timpul de execuț ie în medie este aproximativ jumătate din timpul de execuț ie în cel mai rău caz
timpul, este încă o funcț ie cuadratică de n.
Stabilitate
Deoarece mai multe chei cu aceeaș i valoare sunt plasate în array-ul sortat în aceeaș i ordine
că apar în array-ul de intrare, sortarea prin inserț ie este stabilă.
Memorie suplimentară
Pentru sortarea prin inser ț ie, spunem că timpul de execu ț ie în cel mai rău caz este θ( n2), ș i cel mai bun caz
timpul de execuț ie este θ(n).
Sortarea prin inser ț ie nu folose ș te memorie suplimentară, sortează în loc.
Timpul de sortare prin inser ț ie depinde de ordinea originală a unui input. Acesta durează
timp în Ω(n ) în cel mai rău scenariu, în ciuda faptului că un timp în ordinea nis
2
suficient pentru a rezolva instanț e mari în care obiectele sunt deja sortate.
Sortarea prin bule, cunoscută ș i sub denumirea de sortare prin scufundare, este o metodă simplăalgoritm de sortarecare funcț ionează prin
parcurgând în mod repetat lista care trebuie sortată, comparând fiecare pereche de elemente adiacente
ș ischimbaredacă sunt în ordine greș ită. Trecea prin listă este repetată
până când nu mai sunt necesare schimbări, ceea ce indică faptul că lista este sortată. Algoritmul îș i obț ine
numele provine din modul în care elementele mai mici "bulează" la suprafaț a listei. Pentru că foloseș te doar
comparatii pentru a opera pe elemente, este unsortare prin comparare.
Să luăm tabloul de numere "5 1 4 2 8", ș i să sortăm tabloul de la cel mai mic număr la
cea mai mare număr utilizând algoritmul de sortare prin bulă. În fiecare pas, elementele scrise cu **subliniere**
fiind comparat.
Prima trecere:
(5 14 2 8 ) (1 54 2 8), Aici, algoritmul compară primele două elemente ș i le schimbă.
ei.
( 15 42 8 ) (14 52 8), Schimbă deoarece 5 > 4
( 1 45 28 ) ( 1 42 58 ), Schimbă deoarece 5 > 2
( 1 4 25 8) (1 4 25 8), Acum, deoarece aceste elemente sunt deja în ordine (8 > 5),
algoritmul nu le schimbă.
A doua trecere:
(1 42 5 8 ) (1 42 5 8 )
44
( 14 25 8 ) ( 12 45 8 ), Schimbă deoarece 4 > 2
( 1 24 58 ) ( 1 24 58 )
( 1 2 45 8) ( 1 2 45 8)
Acum, array-ul este deja sortat, dar algoritmul nostru nu ș tie dacă este complet.
algoritmul are nevoie de o singură trecere fără nicio schimbare pentru a ș ti că este sortat.
Al treilea pas:
(1 24 5 8) (1 24 5 8)
( 12 45 8 ) ( 12 45 8 )
( 1 24 58 ) ( 1 24 58 )
( 1 2 45 8) ( 1 2 45 8)
În cele din urmă, array-ul este sortat, iar algoritmul poate termina.
Analiză :
Complexitatea timpului t(n)=
n -1 n − j -1 n −1 n -1
∑ ∑1 = ∑n − j −1 − 0 +1 = ∑
j =1 eu
=0 j =1 =1
n − j = (n −1) + (n − 2) + ... + 3 + 2 +1 = n(n+!)/2
j
Verifică-ț i progresul
1. Write an algorithm for sequential search and trace it for the input { 1,9,2,4,6,8}.
2. Scrie un algoritm pentru sortarea prin bule ș i sortarea prin selecț ie. Aplică-l pentru următorul set de
1.3 SUMMARY:
45
Sortare: Este procesul de aranjare a elementelor fie în ordine crescătoare, fie în ordine descrescătoare.
mod. Exemplu sortare prin inserț ie, sortare prin bulă, sortare prin selecț ie etc.
1.9 KEYWORDS
Căutarea binară: căutarea unui element prin tehnica divizării ș i cuceririi.
1. 1
2. 1.2.1 & 1.2.3
3. 1.2.2
1.7 EXERCI ȚII Ș I RĂSPUNSURI LA SFÂR Ș ITUL UNITĂ ȚII
5. Aplică algoritmul de sortare prin inser ț ie pentru mul ț imea A L G O R I T H M pentru a o sorta în
ordine crescătoare.
6. Aplică Algoritmul de căutare binară pentru a căuta 'G' din setul A B C F H Z X.
VEZI
1. 1.1
2. 1.2
46
MODUL-3, UNITATEA 2: ÎMPARTĂ Ș I CONQUISTĂ
Structură
2.0 Obiective
1.1 Introducere
1.2 Structura generală a strategiilor de împărț ire ș i cucerire
4.0 OBIECTIVE
La sfârș itul acestei unităț i vei fi capabil să
•Găse ș te cum să aplici metoda divide et impera
4.1 INTRODUCERE
Metoda de proiectare a algoritmului prin împărț ire ș i stăpânire este cea mai cunoscută metodă de
Rezolvarea unei probleme. Acum, să vedem "Ce este tehnica divide ș i cucereș te? Ce este
plan general folosind care aceste algoritmi funcț ionează?
Definiț ie: Divide ș i cucereș te este o tehnică de sus în jos pentru proiectarea algoritmilor care
constă în împărț irea problemei în subprobleme mai mici, sperând că soluț iile acestora
sub problemele sunt mai uș or de găsit. Soluț iile tuturor problemelor mai mici sunt apoi combinate
pentru a obț ine o soluț ie pentru problema originală.
Tehnica de divizare ș i cucerire pentru rezolvarea unei probleme implică trei paș i
Fiecare nivel al recursiei:
•.Împăr ț iț i: Problema este împăr ț ită în mai multe subprobleme
47
Conquista: Subproblemele sunt cucerite prin rezolvarea lor recursiv.
sub Problemele sunt mai mici ca dimensiune, problema poate fi rezolvată folosind o abordare directă
metodă
Solu ț iile subproblemelor sunt combinate pentru a ob ț ine solu ț ia pentru
problema mai mare.
Să luăm în considerare o altă problemă simplă care poate fi rezolvată prin împăr ț ire ș i...
tehnica de cucerire.
Problema este de a găsi elementele maxime ș i minime într-un set de 'n' elemente.
48
•Mai important, atunci când elementele din a[1:n] sunt polinoame, vectori, foarte
numere mari, sau ș iruri de caractere, costul unei comparaț ii de elemente este mult
mai mare decât costul celorlalte operaț iuni.
Prin urmare, timpul este determinat în principal de costul total al comparării elementelor.
•Straight MaxMin necesită 2(n-1) compara ț ii de elemente în cel mai bun, mediu ș i cel mai rău caz
cazuri.
Cazul cel mai bun apare acum când elementele sunt în ordine crescătoare.
Numărul de comparaț ii ale elementelor este (n-1).
Cazul cel mai rău apare când elementele sunt în ordine descrescătoare.
Numărul de comparaț ii ale elementelor este 2(n-1)
•În medie, un a[I] este > decât maximul jumătate din timp, ș i astfel, numărul mediu de
comparatia este 3n/2-1.
•A divide- and conquer algorithm for this problem would proceed as follows:
49
găsirea valorii maxime ș i minime din listă.
Dacă lista are mai mult de 2 elemente, P trebuie să fie împăr ț it în instan ț e mai mici.
50
•Procedura este ini ț ial invocată prin afirma ț ia,
MaxMin(1,n,x,y)
•Să presupunem că simulăm MaxMin pe următoarele 9 elemente
Când 'n' este o putere a lui 2, n=2^k pentru un anumit întreg pozitiv 'k', atunci
T(n) = 2T(n/2) + 2
= 2(2T(n/4)+2)+2
= 4T(n/4)+4+2
*
*
= 2^k-1T(2)+
= 2^k-1+2^k-2
= 2^k/2+2^k-2
= n/2+n-2
(n+2n)/2)-2
T(n)=(3n/2)-2
*Reț ineț i că (3n/3)-3 este media cea mai bună ș i numărul de comparaț ii în cel mai rău caz când ‘n’
este o putere a lui 2.
51
4.3 REZOLVAREA ECUAȚIILOR DE RECURENȚĂ
Soluț ie tehnică:
Pasul 1: Stabiliț i o ecuaț ie caracteristică corespunzătoare:
a0xn+ a1x(n-1) + …. + akx(n-k) = 0,
x(n-k) [a0xk+ a1x(k-1) + … +ak] = 0,
Pasul 2: Rezolvaț i ecuaț ia caracteristică ca pe o ecuaț ie polinomială. Să zicem că rădăcinile reale sunt
r1, r2, . . . . ,rk. Observa ț i, există k solu ț ii pentru ecua ț ia polinomială de ordin k.
Pasul 4: Folosind condiț iile iniț iale (dacă sunt disponibile), rezolvaț i pentru coeficienț ii din ecuaț ia de mai sus.
pentru a găsi soluț ia particulară.
Exemplu 1:
Rezolvarea ecuaț iei de recurenț ă tn- 3tn-1- 4tn-2= 0, pentru n >= 2. {Initial condition:
t0=0, t1=1}
Foloseș te t0= c1+ c2= 0 ș i t1= -c1+ 4c21. [Notă, avem nevoie de două condiț ii iniț iale pentru două
coeficienț i.
52
Aș adar, soluț ia particulară este:
tn(1/5)[4n– (-1)n] = Θ(4n)
Soluț ie tehnică:
Exemplu 2:
tn- 2tn-1= 3n. [Observa ț i, acesta este un caz special cu p(n) = 1, polinom de ordinul 0, ș i
nu există o condiț ie iniț ială - aș a că obț inem doar soluț ia generală.
Transformă cu n->n+1:
tn+1 - 2tn= 3n+1 Ecuaț ia(1).
Exemplul 3:
tn- 2tn-1 = n
53
Deci, tn+1 -2tn= n+1
Scăzând prima (dată) ecuaț ie din cea de-a doua ecuaț ie,
tn+1 - 3tn+ 2tn-1 = 1
Încă nu este o ecuaț ie omogenă. A doua etapă a omogenizării,
tn+2 – 3tn+1 + 2tn= 1
Scade încă odată,
tn+2 – 4tn+1 + 5tn- 2tn-1 = 0
Acum este o ecuaț ie de recurenț ă omogenă ș i o poate rezolva în modul obiș nuit.
54
unde fiecare , și este un matrice.
Reț ineț i că Ecuaț ia este o instanț ă a recurenț ei generale date în Ecuaț ia . În acest
caz, a=8, b=2, ș i k=2. Putem obț ine soluț ia direct din Ecuaț ie.
Deoarece , timpul total de execu ț ie este . Dar asta nu
mai bun decât algoritmul original, direct!
Din fericire, se dovedeș te că una dintre cele opt înmulț iri de matrice este redundantă.
Consideraț i următoarea serie de ș apte matrices:
55
Fiecare ecuaț ie de mai sus are doar o înmulț ire. Zece adunări ș i ș apte înmulț iri.
sunt necesare pentru a calcula prin. Dat prin , putem calcula
elementele matricei produsului Cas sunt următoarele:
Ca mai sus, Ecuaț ie este o instanț ă a recurenț ei generale date în Ecuaț ia.
obț inem soluț ia direct din Ecuaț ie. În acest caz, a=7, b=2 ș i k=2.
Prin urmare, ș i timpul total de rulare este (Foloseș te Teorema Master)
56
Unde a=3, b=2 ș i f(n)=nd= 10
T(n)=o(nlog32 ) = o(3logn 2)
Verifică-ț i progresul
1. Explicaț i procesul de împărț ire ș i cucerire.
2. Folosind abordarea divide ș i cucereș te, scrieț i un algoritm pentru a găsi minimul ș i
maximum în tablou.
3. Masteratul de stat
1.4 SUMMARY
Împarte ș i cucereș te: este o tehnică generală de proiectare a algoritmilor care rezolvă o problemă.
instanț ă împărț indu-l în mai multe instanț e mai mici (ideal de dimensiuni egale), rezolvând fiecare
a lor recursiv, ș i apoi combinând soluț iile lor pentru a obț ine o soluț ie pentru original
instanț a problemei. Multe algoritmi eficienț i se bazează pe această tehnică, deș i
poate fi atât inaplicabil, cât ș i inferior la soluț ii algoritmice mai simple.
Eficien ț a temporală T(n) a multor tehnici de împăr ț ire ș i cucerire satisface ecua ț ia
T(n)=aT(n/b)+f(n). Teorema Maestrului stabile ș te ordinea de cre ș tere a acestuia.
soluț ia ecuaț iei.
Algoritmul lui Strassen necesită doar ș apte înmulț iri pentru a înmulț i două matrice 2×2, dar
cere mai multe adăugiri decât algoritmul bazat pe definiț ie. Prin explorarea divizării ș i
2.807
tehnica Conquer, acest algoritm poate înmul ț i două matrice n-la-n în aproximativ n
înmulț iri.
Răspunsuri: VEZI
1. 1.1
2. 1.2
3. 1.1
57
1.11 KEYWORDS
1 θ – Notarea asimptotică
Teorema lui Master - pentru a rezolva relaț iile de recurenț ă ale divizării ș i cuceririi de specific,
formular.
3. Forme omogene ș i neomogene - acestea sunt forme ale ecuaț iilor de recurenț ă.
1. 1.2
2. 1.2
3. 1.3
4. 1.4
1.7 EXERCI ȚII Ș I RĂSPUNSURI LA SFÂR Ș ITUL UNITĂ ȚII
58
MODUL-3, UNITATEA 2: SORTARE
Structură
3.0 Obiective
1.1 Introducere
1.2 Sortare prin îmbinare
5.0 OBIECTIVE
La sfârș itul acestei unităț i vei fi capabil să
•Identificarea diferitelor tipuri de sortare
5.1 INTRODUCTION
59
Îninformaticăalgoritmul de sortare este unalgoritmcare pune elemente de olistăîntr-o
certacomandăCele mai utilizate comenzi sunt ordinea numerică ș iordine lexicografică.
Eficientsortareeste important pentru optimizarea utilizării altor algoritmi (cum ar ficaută
ș ifuzionarealgoritmi) care necesită liste sortate pentru a funcț iona corect; Mai formal,
ieș irea trebuie să satisfacă două condiț ii:
1. Ie ș irea este în ordinea non-descrescătoare (fiecare element nu este mai mic decât
elementul precedent conform dorinț eicomandă totală);
2. Ie ș irea este opermutare, sau reorganizarea, a inputului.
Cele două tehnici de sortare care urmează îndeaproape metoda divide et impera sunt
Sortare prin îmbinare
•Sortare rapidă (sortare prin schimbare de partitie)
1. Dacă lista are lungimea 0 sau 1, atunci este deja sortată. Altfel:
2. Împarte lista nesortată în două subliste de aproximativ jumătate din dimensiune.
3. Sortează fiecare sublistărecursivprin reaplicarea sortării prin fuziune.
4.Îmbinăcele două subliste înapoi într-o listă sortată.
Acum, să vedem "Care sunt paș ii implicaț i în sortarea prin îmbinare?" Paș ii diferiț i care sunt
implicate în timpul sortării folosind sortarea prin interclasare sunt prezentate mai jos:
Împarte: Împarte array-ul dat, care constă din n elemente, în două părț i de n/2.
Căutare element
Conquer: Sortează partea stângă a tabloului ș i partea dreaptă a tabloului recursiv
utilizând sortarea prin îmbinare...
Combină: Combină partea stângă sortată ș i partea dreaptă sortată pentru a obț ine o singură parte sortată.
aranjament.
Operaț ia cheie în sortarea prin interclasă este combinarea părț ii stângi sortate cu partea dreaptă sortată.
parte într-un singur array sortat. Acest proces de unire a două vectori sortati într-un singur
vectorul ordonat se numeș te îmbinare simplă. Singura condiț ie necesară pentru această problemă este că
Ambele aranjamente ar trebui să fie sortate. Acum, să vedem "Cum să proiectăm un algoritm simplu de unire?"
60
dacă ( A[i] < B[j] ) atunci
C[k] A[i]
k k +l, i i+l
Copiază elementul cel mai mic din A în C
//Scop : Combină două array-uri sortate în care primul array începe de la mic la mediu ș i //the
al doilea începe de la mid+1 până la high.
61
altfel
C[k] A[j]
j j+l
k k + 1;
sfârș it dacă
sfârș it în timp ce
Copiează elementul cel mai mic din a doua parte a A în C
// Punct către următorul element în a doua parte a A
// Punctaț i următorul element în C
în timp ce (i <= mijloc) //Copiază articolele rămase din partea stângă a A în C
C[k] A[i]
k k+l , i i+l
finalizare în timp ce
în timp ce (j <= high) //Copiază elementele rămase din partea dreaptă a lui A în C
C[k] A[j]
k k+l; j j+l
sfârș it în timp ce
pentru i = mic la mare
a[i] c[i] // Copiaț i elementele din vectorul C în vectorul A
sfârș it pentru
Odată ce fuzionarea s-a încheiat, putem aranja cu uș urinț ă numerele în ordine crescătoare folosind
sortare prin îmbinare. iflow ș i high sunt limita inferioară ș i limita superioară într-un array, general
procedura de sortare a elementelor folosind sortarea prin interclasare este prezentată mai jos:
62
Sortare prin fuziune (a, jos, mijloc) // Sortează partea stângă a matricei,
Sortare prin combinare (a, mid + 1, high) // Sortează partea dreaptă a array-ului
Sfârș it dacă
Analiză: Este clar din algoritm că instanț a problemei este împărț ită în două
părț i egale.
Dacă timpul pentru operaț iile de îmbinare este proporț ional cu 'n', atunci timpul de calcul pentru
sortarea prin interclasare este descrisă prin relaț ia de recurenț ă.
Când 'n' este o putere a lui 2, n= 2^k, putem rezolva această ecuaț ie prin succesive
substituț ie.
T(n) = 2(2T(n/4) + cn/2) + cn
= 4T(n/4)+2cn
= 4(2T(n/8)+cn/4)+2cn
*
*
= 2^k T(1)+kCn.
= an + cn log n.
Avantaje
Algoritmul merge sort este un algoritm stabil
Poate fi aplicat fi ș ierelor de orice dimensiune.
Dezavantaje
Algoritmul foloseș te un spaț iu suplimentar proporț ional cu N. Aș adar, algoritmul nu este în loc.
Foloseș te mai multă memorie pe stivă din cauza recursiei.
Abordarea de tip divide ș i cucere ș te poate fi utilizată pentru a ajunge la o sortare eficientă.
metodă diferită de sortarea prin îmbinare.
63
În sortarea prin interclasare, fi ș ierul a[1:n] a fost împăr ț it la mijloc în sub-arrays care
au fost sortate independent ș i ulterior combinate.
•Aceasta se realizează prin reorganizarea elementelor din a[1:n] astfel încât a[I]<=a[j] pentru
toate i între 1 ș i n ș i toate j între (m+1) ș i n pentru un anumit m, 1<=m<=n.
•Nu este necesară nicio îmbinare. Această reorganizare este denumită partitionare.
•Se presupune că a[p]>=a[m] ș i că a[m] este elementul de parti ț ionare. Dacă m=1 &
p-1=n, atunci a[n+1] trebuie să fie definit ș i trebuie să fie mai mare sau egal cu to ț i
elemente în a[1:n]
Presupunerea că a[m] este elementul de parti ț ie este doar pentru comoditate, altceva
alegerile pentru elementul de partiț ie decât primul element din set sunt mai bune în
practică.
64
Algoritm: Partț ionaț i array-ul a[m:p-1] în jurul a[m]
1. Algoritm Partitie(a,m,p)
2. //în cadrul a[m],a[m+1],…..,a[p-1] elementele
3. // sunt reorganizate în a ș a fel încât dacă
4. //ini ț ial t=a[m], apoi după finalizare
5. //a[q]=t pentru un anumit q între m ș i
6. //p-1,a[k]<=t pentru m<=k<q, ș i
7. //a[k]>=t pentru q<k<p. q este returnat
8. //Seta ț i a[p]=infinit.
9. {
10. v=a[m];I=m;j=p;
11. repetă
12.
65
13. repetă
14. I=I+1;
15. până când(a[I]>=v);
16. repetă
17. j=j-1;
18. până când(a[j]<=v);
19. dacă (I<j) atunci interschimbă(a,I.j);
20. }până(I>=j);
21. a[m]=a[j]; a[j]=v;
22. retun j;
23. }
1. Algoritmul Interschimbare(a,I,j)
//Schimbă a[I] cu a[j]
3. {
4. p=a[I];
5. a[I]=a[j];
6. a[j]=p;
7. }
Algoritmul Quicksort(p,q)
//Sortează elementele a[p],....a[q] care se află
2. //este tabloul global a[1:n] în ordine crescătoare
3. //comandă; a[n+1] este considerat a fi definit
4. // ș i trebuie să fie >= toate elementele din a[1:n]
5. {
6. dacă(p<q) atunci // Dacă există mai mult de un element
7.
8. // împăr ț iț i p în 2 subprobleme
9. j=partition(a,p,q+1);
10. //’j’ este poziț ia elementului de partiț ionare.
11. //rezolvă subproblemele.
12. quicksort(p,j-1);
13. quicksort(j+1,q);
14. //Nu este nevoie de combinarea soluț iei.
15. }
16. }
Design:
Sortarea rapidă se bazează pe principiul „Împarte ș i cucereș te”. Sortarea rapidă funcț ionează
foarte bine pe un set mare de date. Acum, să vedem "Care sunt paș ii
implicate în sortarea rapidă?
sortarea este prezentată mai jos:
66
Partea stângă Element pivot Partea dreaptă
A[0]A[1]….A[K-1] A[K] A[K+1]A[K+2]…..A[N-1]
Pentru a simplifica designul, presupuneț i că o valoare foarte mare este stocată la sfârș itul
array. Acest lucru se realizează prin stocarea 00 în a[n]. Pe lângă a, low ș i high, ceilalț i
variabilele care sunt utilizate sunt:
Valoarea iniț ială a indexului i este scăzută, adică, i valoarea iniț ială a indexului j este unu
mai mult decât înalt, adică, j înalt
.pivot:a[low] este tratat ca elementul pivot.
Procedura generală pentru a partitiona array-ul este prezentată mai jos:
Continuaț i să incrementaț i indexii atâta timp cât sunt pivot. a[i]. Acest lucru se realizează folosind
statement:
oare eu i + 1 în timp ce (pivot >= a[i]);
.. Odată ce condiț ia de mai sus eș uează, continuaț i să decrementezi indexul cât timp pivotS a[j]'
Acest lucru se realizează folosind declaraț ia:
fă j +- j - 1 cât timp (pivot >= a[i]);
Odată ce condiț ia de mai sus nu mai este îndeplinită, dacă i este mai mic decât j, schimbă a[i] cu a[j] ș i repetă tot.
procesul de mai sus atâta timp cât i <= j.
Cel mai bun lucru care s-ar putea întâmpla în sortarea rapidă ar fi ca fiecare etapă de partiț ionare
împarte matricea exact în jumătate. Cu alte cuvinte, cel mai bine este să fie o mediană a cheilor din
A[p. .r] every time procedure 'Partition' is called. The procedure 'Partition' always split
array-ul care trebuie sortat în două array-uri de dimensiuni egale.
Dacă procedura 'Partiț ie' produce două regiuni de dimensiune n/2, relaț ia de recurenț ă este
atunci
67
T(n)=T(n/2)+T(n/2)+ (n)
= 2T(n/2) + (n)
T(n) = (nlgn)
undeqruns de la 1 ton-1, deoarece partiț ia produce două regiuni, fiecare având dimensiune la
cel puț in 1.
Deoarece derivata a doua a expresiei q2+ (n-q)2în ceea ce priveș te q este pozitiv.
Prin urmare, expresia atinge un maxim în intervalul 1≤ q ≤ n -1 la unul dintre
punctele finale. Aceasta oferă limita maximă (q2+ (n-q)2)) 1 + (n-1)2 =n2+ 2(n-1).
Deoarece putem alege constanta astfel încât termenul 2c(n-1) să domine termenul (n) noi
a avea
T(n) ≤ cn2
Astfel, timpul de execuț ie în cel mai rău caz al sortării rapide este T(n) = (n2).
68
Analiza cazului mediu
LetT(n) denotă timpul mediu necesar pentru a sorta un tablou de n elemente. Un apel la
RANDOMIZED_QUICKSORT cu un array de 1 element durează un timp constant, aș a că avem
T(1) = (1).
După împărț ire, RANDOMIZED_QUICKSORT se apelează singur pentru a sorta două sub-array-uri. The
timpul mediu pentru a sorta un array A[1 . .q] este T[q] ș i timpul mediu pentru a sorta un array
A[q+1 . .n] este T[n-q]. Avem
Rezolvă recurenț a de mai sus folosind metoda substituț iei. Presupune inductiv că T(n) ≤
anlgn+b pentru unele constante a> 0 ș i b> 0.
Dacă putem alege 'a' ș i 'b' suficient de mari astfel încât nlgn+b > T(1). Atunci pentru n > 1, avem
n-1
T(n) ≥ ∑k=1 2/n (aklgk + b) + (n)
= 2a/nn-1∑k=1klgk -1/8(n2) + 2b/n(n-1) + (n) ------- 4
n-1
∑klgk
k=1 ≤ 1/2 n2lgn -1/8(n2)
Introdu această afirmaț ie în ecuaț ia 4 de mai sus ș i obț inem
69
T(n) ≤ 2a/n[1/2n2lgn- 1/8(n2)] + 2/n b(n-1) + (n)
≤ anlgn-an/4 + 2b + (n)
Concluzie :
Sortarea rapidă este un algoritm de sortare in situ, al cărui timp de execuț ie în cel mai rău caz este (n2) ș i
timpul de execuț ie aș teptat este (nlgn), unde constantele ascunse în (nlgn) sunt mici.
Ideea de bază este să începem cu o examinare a elementului din mijlocul array-ului. Aceasta
va duce la 3 situaț ii posibile:
Dacă aceasta se potriveș te cu ț inta K, atunci căutarea poate termina cu succes, prin imprimarea.
indexul elementului în masiv.
Pe de altă parte, dacă K<A[middle], atunci căutarea poate fi limitată la elementele din stânga
A[mijloc]. Toate elementele din dreapta mijlocului pot fi ignorate.
Dacă se dovedeș te că K > A[middle], atunci căutarea ulterioară este limitată la elementele din dreapta.
al A[mijloc].
Dacă toate elementele sunt epuizate ș i ț inta nu este găsită în array, atunci metoda
întoarce o valoare specială, cum ar fi -1.
Aici este o versiune a funcț iei de Căutare Binara:
70
Algorithm : BinarySearch (int A[ ], int n, int K)
{
L=0, Mid, R=n-1;
în timp ce (L<=R)
{
Mid = (L + R)/2;
dacă ( K == A[Mid] )
returnează Mid;
altfel dacă ( K > A[Mid] )
L = Mid + 1;
altfel
R = Mid - 1 ;
}
return –1 ;
}
Analiza căutării binare
Cazul cel mai bun: Cazul cel mai bun apare atunci când elementul căutat este prezent în mijlocul
array-ul. Deci numărul total de comparaț ii necesar va fi 1.. Prin urmare, timpul
complexitatea căutării binare în cel mai bun caz este dată de Tbest(n)=Ω(1).
Cazul cel mai rău: Acest caz apare atunci când cheia care trebuie căutată se află fie în prima poziț ie
sau în ultima poziț ie din array. În astfel de situaț ii, numărul maxim de elemente
comparările sunt necesare, iar complexitatea temporală este dată de
T(n)={ 1 dacă n=1
T(n/2) + 1 altfel
Considera, t(n)=t(n/2)+1
Această relaț ie de recurenț ă poate fi rezolvată folosind substituț ia repetată, aș a cum este prezentat mai jos:
t(n)=t(n/2)+1 înlocuiț i n cu n/2
t(n)=1+1+t(n/2 ) 2
71
Verifică-ț i progresul
1. Ce este sortarea?
2. Scrie un algoritm pentru sortarea prin interclasare? Explică modul în care funcț ionează.
3. Scrie un algoritm pentru sortarea rapidă? calculează cazul cel mai bun, cazul cel mai rău ș i cazul mediu
complexitate temporală.
4. Explicaț i funcț ionarea căutării binare cu un exemplu? Scrieț i un algoritm ș i timpul acestuia
complexitate.
5.5 SUMMARY
Sortarea prin îmbinarea este un algoritm de tip divide ș i cucereș te. Funcț ionează prin împărț irea unei matrice în două
jumătă ț i, sortându-le recursiv ș i apoi fuzionând cele două jumătă ț i sortate pentru a ob ț ine
array-ul original sortat. Eficienț a temporală a algoritmului este aceeaș i în toate cazurile adică θ(nlogn).
Sortarea rapidă este un algoritm de împăr ț ire ș i cucerire care func ț ionează prin partitionarea inputului său.
elemente în funcț ie de valoarea lor relativă faț ă de un element preselectat. Sortarea rapidă este
notat pentru eficienț a sa superioară printre algoritmii nlogn pentru sortarea ordonărilor aleatoare
matrici, dar ș i pentru eficienț a quadratică în cel mai rău caz.
Căutarea binară este un algoritm O(logn) pentru căutarea în aranjamente sortate. Este un exemplu tipic de
o aplicaț ie a tehnicii de împărț ire ș i stăpânire pentru că trebuie să rezolve doar una
problema de jumătate din dimensiune la fiecare dintre iteraț iile sale.
72
12. Aplică algoritmul de sortare prin interclasare pentru a sorta A L G O R I T H M în ordine alfabetică? Este
73
MODUL-3, UNITATEA 3: TEHNICA AVARĂ
Structură
4.0 Obiective
1.1 Introducere
1.1.1 Conceptul metodei zgârcite
1.2 Probleme de optimizare
1.3 Rezumat
1.4 Cuvinte cheie
6.0 OBJECTIVES
La sfârș itul acestei unităț i vei fi în măsură să
6.1 INTRODUCERE
Algoritmii zgârci ț i sunt simpli ș i direc ț i. Sunt pe termen scurt în viziunea lor.
abordare în sensul că iau decizii pe baza informaț iilor disponibile fără
îngrijorându-se cu privire la efectul pe care aceste decizii îl pot avea în viitor. Ele sunt uș or de imaginat,
uș or de implementat ș i, cel mai adesea, destul de eficient. Multe probleme nu pot fi rezolvate
corect prin abordarea greedy. Algoritmii greedy sunt folosiț i pentru a rezolva probleme de optimizare
74
1.1.1 Conceptul metodei greedy
Algoritmul gloton func ț ionează prin luarea deciziei care pare cea mai promi ț ătoare în orice moment.
moment; nu reconsideră niciodată această decizie, indiferent de situaț ia care ar putea apărea mai târziu.
Problemă: Fă o schimbare a unei sume date folosind cel mai mic număr posibil de
monede.
Algoritm informal
Începe cu nimic.
•în fiecare etapă fără a depă ș i suma dată.
•adauga-l pe cel mai mare la monedele deja alese.
Algoritm Formal
Fă schimb pentru n unităț i folosind cel mai mic număr posibil de monede.
MAKE-CHANGE(n) {
Sum ← 0
În timp ce suma != n
75
x=cel mai mare element din setul C astfel încât suma+x <= n
Fără soluț ie
S ← S{valoareadx}
sumă ← sumă+x
ÎNTOARCE S }
Fă o schimbare pentru 2.89 (289 cenț i) aici n = 2.89 ș i soluț ia conț ine 2
dolari, 3 sferturi, 1 dime ș i 4 bănuț i. Algoritmul este lacom deoarece în fiecare etapă
alege cea mai mare monedă fără a se îngrijora de consecinț e. Mai mult, niciodată nu
îș i schimbă părerea în sensul că, odată ce o monedă a fost inclusă în setul de soluț ii, aceasta
rămâne acolo.
Pentru a construi soluț ia într-un mod optim. Algoritmul menț ine două seturi. Unul conț ine
articole alese ș i cealaltă conț ine articole respinse.
1. O func ț ie care verifică dacă setul de articole ales oferă o solu ț ie.
2. O func ț ie care verifică fezabilitatea unui set.
3. Func ț ia de selec ț ie indică care dintre candida ț i este cel mai promi ț ător.
4. O func ț ie obiectivă, care nu apare explicit, oferă valoarea unui
soluț ie.
Ini ț ial, setul de articole alese este gol, adică setul de solu ț ii.
•La fiecare pas
obiectul va fi adăugat într-un set de solu ț ii prin utilizarea func ț iei de selec ț ie.
dacă setul nu ar mai fi fezabil
. respinge articolele aflate în discuț ie (ș i nu va mai fi considerat niciodată din nou).
ALT IF set este încă fezabil ATUNCI
. adaugă articolul curent.
76
1.1.3 Defini ț ii ale fezabilită ț ii
Un set fezabil (de candidaț i) este promiț ător dacă poate fi extins pentru a produce nu doar o
soluț ie, dar o soluț ie optimă pentru problemă. În special, mulț imea vidă este
întotdeauna promiț ător de ce? (pentru că o soluț ie optimă există întotdeauna)
Spre deosebire de Programarea Dinamică, care rezolvă subproblemele de jos în sus, o abordare greedy
strategia progresează de obicei într-o manieră de sus în jos, făcând o alegere lacomă după alta
unul, reducând fiecare problemă la una mai mică.
Se spune că o soluț ie global optimă poate fi obț inută prin realizarea unei soluț ii locale optime.
alegere.
Codul Huffman este o tehnică pentru comprimarea datelor. Algoritmul lacom al lui Huffman analizează
apariț ia fiecărui caracter ș i acesta ca un ș ir binar într-un mod optim.
Exemplu
Să presupunem că avem un set de date care constă din 100.000 de caractere pe care dorim să le comprimăm.
caracteristicile din date apar cu frecvenț ele următoare.
a b c d e f
Frequency 45,000 13,000 12,000 16,000 9,000 5,000
77
Consideraț i problema proiectării unui "cod de caractere binar" în care fiecare caracter este
reprezentat printr-un ș ir binar unic.
În codul de lungime fixă, sunt necesare 3 biț i pentru a reprezenta ș ase (6) caractere.
a b c d e f
Frecvenț ă 45,000 13,000 12,000 16,000 9,000 5,000
Lungime Fixă
000 {"001":"001"}
010 011 100 101
cod
Această metodă necesită 3000.000 de biț i pentru a codifica întreaga fiș ier.
Concluzie
Codul de lungime fixă necesită 300.000 de biț i, în timp ce codul variabil necesită 224.000 de biț i.
Coduri de Prefix
În care nicio cuvânt de cod nu este un prefix al altui cuvânt de cod. Motivul pentru care codurile de prefix sunt
dorit este ca ei să efectueze pur ș i simplu codificarea (compresia) ș i decodificarea.
a b c d e f
Frecvenț ă 45,000 13,000 12,000 16,000 9,000 5,000
Lungime fixă
0 101 100 111 1101 1100
cod
78
Caracterul 'a' este 45.000
fiecare caracter 'a' asignat un cod de 1 bit.
1 * 45.000 = 45.000 biț i.
Codarea ș irurilor
CEAI 10 00 010
MARE 011 00 010
ZECE 10 00 110
Din tabela de coduri de lungime variabilă, codificăm fi ș ierul de 3 caractere abc ca:
a b c
=> 0.101.100 =
0 101 100
0101100
Decodare
Deoarece niciun cuvânt cod nu este un prefix al altuia, cuvântul cod care începe un fiș ier codificat este
neambiguu.
79
Pentru a decoda (a traduce înapoi la caracterul original), elimină-l din fiș ierul codificat ș i
analiza repetată.
De exemplu, în tabelul "cuvânt cod de lungime variabilă", ș irul 001011101 se analizează în mod unic
ca 0.0.101.1101, care este decodificat toaabe.
Reprezentarea "procesului de decodare" este un arbore binar, ale cărui frunze sunt caractere.
interpretează codul binar pentru un caracter ca fiind calea de la rădăcină până la acel caracter
unde 0 înseamnă "mergi la copilul din stânga" ș i 1 înseamnă "mergi la copilul din dreapta". Observaț i că un
Codul optim pentru un fiș ier este întotdeauna reprezentat de un arbore binar complet.
1.2.2 Algoritmul lui Dijkstra (Algoritmul drumului cel mai scurt de la o sursă unică)
Algoritmul lui Dijkstra rezolvă problema căii celei mai scurte dintr-o sursă unică atunci când toate marginile au
greutăț i non-negative. Este un algoritm glutton. Algoritmul începe de la vârful sursă, s, el
creș te un copac, T, care în final acoperă toate vârfurile accesibile din S. Vârfurile sunt adăugate la
T în ordinea distanț ei adică, mai întâi S, apoi vârful cel mai apropiat de S, apoi următorul cel mai apropiat, ș i aș a mai departe
Implementarea următoare presupune că graful G este reprezentat prin adiacentă.
Declaraț ia problemei: Găsirea celei mai scurte distanț e de la o sursă unică la diferite
oraș e.
Pasul 1. Dat graful iniț ial G=(V, E). Toate nodurile au cost infinit, cu excepț ia
nod sursă, s, care are cost 0.
80
Pasul 2. Mai întâi alegem nodul, care este cel mai apropiat de nodul sursă, s. Inicializăm d[s]
0. Adaugă-l la S. Relaxează toate nodurile adiacente sursei, s. Actualizează predecesorul (vezi săgeata roș ie
în diagrama de mai jos) pentru toate nodurile actualizate.
Pasul 3. Alegeț i nodul cel mai apropiat, x. Relaxaț i toate nodurile adiacente nodului x. Actualizaț i
predecesorii pentru nodurile u, v ș i y (din nou, observaț i săgeț ile roș ii în diagrama de mai jos).
Pasul 4. Acum, nodul y este nodul cel mai aproape, aș a că îl adăugăm la S. Relaxaț i nodul v ș i ajustaț i-l.
predecesor (să ne amintim de săgeț ile roș ii!).
81
Pasul 5. Acum avem nodul u care este cel mai apropiat. Alegeț i acest nod ș i ajustaț i vecinul său.
nod v.
Pasul 6. În cele din urmă, adăugaț i nodul v. Lista de predecesori defineș te acum calea cea mai scurtă de la fiecare
nodul sursă, s.
82
Analiză
Verifică-ț i progresul
3. Scrie un algoritm pentru calea cea mai scurtă de la o sursă folosind tehnica greedy, explică.
cu exemplul.
1.3 SUMMARY
Tehnica lacomă sugerează construirea unei soluț ii pentru o problemă de optimizare
printr-o secvenț ă de paș i, fiecare extinzând o soluț ie parț ial construită obț inută astfel
departe, până când se ajunge la o soluț ie completă a problemei. La fiecare pas, alegerea făcută
trebuie să fie fezabil, local optim ș i irrevocabil.
Algoritmul lui Dijkstra rezolvă problema celui mai scurt drum dintr-o sursă unicată de a găsi cel mai scurt
căile de la un vârf dat (sursa) către toate celelalte vârfuri ale unui graf ponderat sau
digraph.
Codul Huffman este un schema de codificare optimă, fără prefix, cu lungime variabilă, care atribuie bit
ș ir de caractere bazat pe frecvenț ele lor într-un text dat. Acest lucru se realizează printr-o
construcț ia lacomă a unui copac binar a cărui margini sunt etichetate cu 0 ș i 1.
1.4KEYWORDS
1 Tehnica lacomă – Este o metodă (abordare) de rezolvare a problemelor.
2. Arborele lui Huffman - Este un arbore binar generat de algoritmul Huffman având copil stâng
greutatea muchiei ca 0 ș i greutatea copilului din dreapta ca 1.
1. 1.1
83
2. 1.2
3. 1.2
1.6 EXERCI ȚII Ș I RĂSPUNSURI LA SFÂR Ș ITUL UNITĂ ȚII
răspunde cu exemplul.
2. Discutaț i cum algoritmul lui Dijkstra aparț ine tehnicii greedy cu exemplul.
Answers: SEE
1. 1.3
2. 1.3
1.7 SUGGESTED READINGS
1. Introducere în proiectarea ș i analiza algoritmilor de Anany Levitin
2. Analiza ș i proiectarea algoritmilor cu C/C++ - 3rdediț ie de Prof. Nandagopalan
3. Analiza ș i proiectarea algoritmilor de către Padma Reddy
84
MODULE-3,UNIT 3: APLICAȚII ALE METODEI GREEDY
Structură
5.0 Obiective
1.1 Introducere
1.2 Problema încărcării containerelor
7.0 OBIECTIVE
La sfârș itul acestei unităț i vei fi capabil să
•Rezolvarea problemelor de încărcare a containerelor ș i a problemelor de rucsac.
•Găsi ț i cele mai scurte drumuri folosind algoritmul lui Prim ș i algoritmul lui Kruskal.
7.1 INTRODUCERE
DEFINIȚIE:
O problemă cu N intrări va avea anumite constrângeri. Orice submul ț ime care le îndepline ș te pe acestea.
restricț iile sunt denumite o soluț ie fezabilă.
O solu ț ie fezabilă care poate maximiza sau minimaliza o func ț ie de obiective dată.
se numeș te o soluț ie optimă.
85
Problema încărcării containerelor este aproape similară cu problema rucsacului ș i de asemenea
similar cu o altă problemă interesantă numită problema de ambalare. Încărcarea containerelor
este afirmat după cum urmează:
Avem containere de dimensiuni egale care trebuie să fie încărcate pe marfă, iar la rândul său, marfa trebuie să fie
a fi încărcat pe navă. Fiecare container are o greutate, wi, iar încărcătura are o maximă
capacitatea unităț ilor c. Obiectivul acestei probleme este de a încărca nava cu maxim
numărul de containere. Să fie xi o variabilă, care ia valori 0 sau 1. Un 1 indică faptul că
containerul trebuie încărcat ș i un 0 înseamnă că nu ar trebui.
În mod formal, putem defini problema ca fiind:
Maximează
Supus constrângerilor, de la i=1 la n, [Link]<= C
Strategia lacomă
În această problemă, din fericire, nu avem profitul care trebuie luat în considerare pentru
constraints. Since the objective is to load the maximum number of containers, the
strategia lacomă pe care o folosim este:
Includeț i containerele de la cel mai mic la cel mai mare (adică în ordine crescătoare a greutăț ilor)
greutăț i astfel încât să putem încărca mai multe containere.
Exemplu
Consideraț i un container cu instanț e de încărcare cu n=7,
{w1,w2,w3,w4,w5,w6,w7}={90,190,40,80,140,40,40,10} and C=300.
Sol: Când containerele sunt aranjate în ordinea crescătoare a greutăț ilor lor, noi
get {w1,w2,w3,w4,w5,w6,w7}={ 10, 40, 40,80,90,140,190}
={ 1, 1, 1 , 1 , 1, 0, 0 }
Prin urmare, soluț ia este {1,0,1,1,0,1,1}
Numărul total de containere=5
Total weight=260
86
Există două versiuni ale problemei
. ?????
•ni se dau n obiecte ș i un rucsac sau sac cu capacitatea M pentru obiectul I are un
greutate Wi unde I variază de la 1 la N.
Problema este că trebuie să umplem geanta cu ajutorul N obiecte ș i rezultatul
profitul trebuie să fie maxim.
•Problema poate fi formulată formal ca
Maximizaț i xipi subiecț i la XiWi<=M
Unde Xi este fracț ia obiectului ș i se află între 0 ș i 1.
Există atât de multe modalită ț i de a rezolva această problemă, ceea ce va oferi multe solu ț ii fezabile.
soluț ia pentru care trebuie să găsim soluț ia optimă.
•Dar în acest algoritm, va genera doar o singură solu ț ie care va fi
fezabil, cât ș i optim.
În primul rând, găsim rata de profit ș i greutatea fiecărui obiect ș i o sortăm.
în conformitate cu ordinea descrescătoare a rapoartelor.
87
•Selecta ț i un obiect cu cel mai mare raport p/w ș i verifica ț i dacă înăl ț imea acestuia este mai mică decât
capacitatea bagajului.
•Dacă da, plasa ț i 1 unitate din primul obiect ș i decrementează capacitatea sacului cu
greutatea obiectului pe care l-aț i plasat.
•Repeta ț i pa ș ii de mai sus până când capacitatea sacului devine mai mică decât greutatea
al obiectului pe care l-aț i selectat. în acest caz, plasaț i o fracț iune a obiectului ș i
ieș i din buclă.
•Ori de câte ori ai selectat.
Cea mai comună formulare a problemei este problema rucsacului 0-1, care
restricț ionează număruleude copii ale fiecărui tip de obiect la zero sau unu. Matematic,
Problema rucsacului 0-1 poate fi formulată ca:
. maximiza
. subiect la
Problema rucsacului cu limită restricț ionează numărul xeude copii ale fiecărui tip de articol la
o valoare întreagă maximăeu. Din punct de vedere matematic, problema rucsacului limitat poate fi
formulat ca:
. maximiza
. subiect la
Algoritm: Rucsac(n,m,w,p,v)
n - numărul de obiecte de selectat
capacitatea rucsacului
w – greutatea tuturor obiectelor
p - profiturile tuturor obiectelor
v - soluț ia optimă pentru numărul de obiecte selectate cu specificaț iile date
capacitate rămasă
88
Altfel dacă(w[i]>j)
v[i,j]=v[i-1,j]
altfel
v[i,j]=max(v[i-1,j],v[i-1,j-w[i]]+p[i])
sfârș it dacă
sfârș it pentru
sfârș it pentru
Algoritm: obiectselectat(n,m,w,v,x)
0 la n-1 face
Pentru i
X[i]=0
Sfârș it pentru
I=n; j=m
Cât timp( i != 0 ș i j != 0)
{
Dacă(v[I,j] != v[i-1,j])
{ x[i]=1; j=j-w[i] }
}
i=i-1
}
Pentru i 1 până la n face
Dacă(x[i]=1)
obiectul pe care l-am selectat
Sfârș it dacă
Sfârș it pentru
Example :
Având unele articole, împachetează rucsacul pentru a obț ine valoarea totală maximă. Fiecare articol are
o greutate ș i o valoare. Greutatea totală pe care o putem transporta nu este mai mult decât o valoare fixă
numărul W. Aș a că trebuie să luăm în considerare greutăț ile elementelor, precum ș i
valoarea lor.
Item #Weight Value
1 2 12
2 1 10 Capacitatea maximă este adică M=5
3 3 20
4 2 15
89
Sol: profitul optim obț inut este 37 prin selectarea obiectelor 1, 2 ș i 4.
Un arbore de acoperire al unui graf este orice arbore care include fiecare vârf din graf. Puț in mai mult
Formal, un arbore de acoperire al unui graf G este un subgraf al lui G care este un arbore ș i conț ine toate
vârfurile lui G. O margine a unui arbore acoperitor se numeș te ramură; o margine în grafic care este
nu face parte din arborele de acoperire se numeș te un chord. Construim arbore de acoperire de fiecare dată când dorim
a găsi o modalitate simplă, ieftină ș i totuș i eficientă de a conecta un set de terminale (calculatoare,
mari, fabrici, etc.). Arborii acoperiț i sunt importanț i din următoarele motive.
Un arbore de acoperire de minimum (MST) al unui graf ponderat G este un arbore de acoperire al lui G al cărui
suma marginilor este greutatea minimă. Cu alte cuvinte, un MST este un arbore format dintr-un subsistem de
Fie G=(V, E) un graf conectat, neorientat unde V este un set de vârfuri (noduri) ș i E
este setul de muchii. Fiecare muchie are o lungime dată, non negativă.
1 ALGORITMUL PRIM'S:
Acest algoritm a fost propus prima dată de Jarnik, dar este în general atribuit lui Prim. Acesta începe de la
un vârf arbitrar (rădăcină) ș i la fiecare etapă, adaugă o nouă ramură (muchie) la arborele existent
construit; algoritmul se opreș te când toate vârfurile din graf au fost atinse.
90
Această strategie este lacomă în sensul că la fiecare pas, arborele parț ial de acoperire este
augmentat cu un vârf care este cel mai mic dintre toate margini adiacente posibile.
Example :
Începe de la un vârf arbitrar (rădăcină). La fiecare etapă, adaugă o nouă ramură (muchie) la
arborele deja construit; algoritmul se opreș te atunci când toate vârfurile din graf au fost
ajuns.
Algoritmulprims(e,cost,n,t)
Mincost :=cost[k,l];
T[1,1]:=k; t[1,2]:=l;
Pentru I:=1 la n fă
{
Fie j un index astfel încât near[j]≠0 ș i
Cost[j,near[j]] este minim;
T[i,1]:=j; t[i,2]:=near[j];
Mincost:=mincost+ Cost[j,near[j]];
91
Aproape[j]:=0;
Pentru k:=0 până la n face
Algoritmul prim va începe cu un arbore care include doar o muchie de cost minim.
al lui G.
•Apoi, muchiile sunt adăugate în copac câte una. următoarea muchie (i,j) care va fi adăugată în
astfel încât I este un vârf inclus în arbore, j este un vârf care nu este încă inclus, iar cost
din (i,j), cost[i,j] este minim dintre toate marginile.
Func ț ionarea primilor va fi explicată prin următorul diagram.
Step 1: Pasul 2:
Pasul 3: Step 4:
Pasul 5: Step 6:
92
Analysis:
Algoritmul îș i petrece cea mai mare parte a timpului căutând cea mai mică muchie. Aș adar, timpul de
algoritmul depinde în esenț ă de modul în care căutăm această margine.
Metodă simplă
Caută doar cea mai mică muchie căutând în lista de adiacenț ă a vârfurilor în V. În acest
în cazul fiecărei iteraț ii, costul este O(m), generând un timp total de execuț ie de O(mn).
• În acest algoritm, un arbore minim de costuri 'T' este construit muchie cu muchie.
• Muchiile sunt luate în considerare pentru incluziunea în 'T' în ordine crescătoare a costului lor.
Algoritm:
Algoritmul kruskal(E,cost,n,t)
//E un set de laturi în G are „n” vârfuri.
//cost[u,v] costul muchiei (u,v).t setul de muchii în arborele acoperitor minim de cost
// primul cost este returnat.
{
pentru i=1 până la n fă parent[I]=-1;
I=0;mincost=0.0;
While((I<n-1) ș i (heap-ul nu este gol)) do
{
j=găseș te(n);
93
k=găseș te(v);
dacă(j nu este egal cu k) atunci
{
i=i+1
t[i,1]=u;
t[i,2]=v;
mincost=mincost+cost[u,v];
uniune(j,k);
}
}
daca(i nu este egal cu n-1) atunci scrie(„Niciun arbore de întindere”)
altfel returnează costul minim;
}
Analiză
Complexitatea temporală a algoritmului pentru arborele de acoperire de cost minim în cel mai rău caz este
O(|E|log|E|)
unde E este mulț imea muchiilor lui G.
Pasul 1. În grafic, muchia(g, h) este cea mai scurtă. Fiecare vertex g, fie vertex h ar putea fi
reprezentant. Să alegem vârful g în mod arbitrar.
Pasul 2. Muchia (c, i) creează al doilea arbore. Alegeț i vârful c ca reprezentant pentru
al doilea copac.
94
Pasul 3. Muchia (g, g) este următoarea cea mai scurtă muchie. Adaugă această muchie ș i alege vârful g ca
reprezentant.
Pasul 5. Adăugaț i muchia (c, f) ș i combinaț i cele două arbori. Vârful c este ales ca reprezentant.
Pasul 6. Muchia (g, i) este următoarea cea mai ieftină, dar dacă adăugăm această muchie, ar apărea un ciclu.
95
Pasul 8. Dacă adăugăm muchia (h, i), muchia (h, i) ar forma un ciclu.
Pasul 9. În loc să adăugaț i latura (h, i), adăugaț i latura (a, h).
Pasul 10. Din nou, dacă adăugăm muchia (b, c), ar crea un ciclu. Adăugaț i în schimb muchia (d, e) pentru
completează arborele acoperitor. În acest arbore acoperitor, toate arborii sunt conectaț i, iar vârful c este unică.
reprezentant.
96
Verifică-ț i progresul
SUMMARY:
Problema încărcării containerelor este de a umple un număr mai mare de containere în navă supusă la
unele constrângeri specificate.
Problema rucsacului constă în selectarea obiectelor din n obiecte care oferă un profit mai mare ș i
în care suma greutăț ii obiectelor selectate nu ar trebui să depăș ească greutatea rucsacului.
Prims ș i Kruskal sunt cele două algoritmi pentru a genera arbori minimi de conexiune. Aș a că
cineva poate traversa cu uș urinț ă întregul graf cu costuri mai mici.
1.13 KEYWORDS
1 Arbore minim de acoperire - acesta este un arbore care constă din toate vârful din grafic cu foarte
un număr mic de muchii ș i de asemenea greutatea totală a arborelui acoperitor este minimă.
1. 1.2
2. 1.3
3. 1.4(1)
4. 1.4(2)
1.7 EXERCI ȚII Ș I RĂSPUNSURI LA FINALUL UNITĂ ȚII
13. List out the difference between Prim’s algorithm and Kruskal’s algorithm.
14. Compară problema încărcării containerelor cu problema rucsacului
Answers: SEE
1. 1.4 (1 & 2)
97
2. 1.2 & 1.3
98
MODULUL-4, UNITATEA 1 INTRODUCERE ÎN GRAFURI
Structură
1.0 Obiective
1.1 Grafuri ca structuri de date
1.2 Reprezentarea grafică
Matrice de adiacentă
Lista de adiacen ț ă
1.3 Parcurgerea prin adâncime (DFS)
1.4 Rezumat
1.5 Keywords
1.6 Răspunsuri pentru a verifica progresul tău
1.7 Exerci ț ii finale ș i răspunsuri
1.8 Suggested readings
8.0 OBIECTIVE
La sfârș itul acestei unităț i vei fi capabil să
Grafurile sunt o structură folosită pe scară largă în informatică ș i în diferite domenii ale calculatoarelor.
aplicaț ii. Nu spunem structură de date aici ș i vedem diferenț a. Grafurile înseamnă să
stochează ș i analizează metadatele, conexiunile care sunt prezente în date. De exemplu,
considera ț i ora ș ele din ț ara dumneavoastră. Reteaua de drumuri, care le conectează, poate fi
reprezentate ca un grafic ș i apoi analizate. Putem examina dacă o anumită oraș poate fi atins
dintr-o altă parte sau găseș te cea mai scurtă rută între două oraș e.
În primul rând, introducem câteva definiț ii despre grafuri. Apoi, vom arăta,
cum sunt reprezentate grafurile în interiorul unui computer. Apoi poț i trece la grafurile de bază
algoritmi.
Există două seturi importante de obiecte, care specifică graficul ș i structura sa. Primul set
isV, care se numeș te setul de vârfuri. În exemplul cu reț eaua de drumuri, oraș ele sunt vârfuri.
99
Fiecare vârf poate fi desenat ca un cerc cu numărul vârfului în interior.
vârfuri
Următorul set important este E, care se numeș te setul de muchii. E este un subset al V x V. Pur ș i simplu
în termeni de vorbire, fiecare muchie leagă două vârfuri, inclusiv cazul în care un vârf este
conectat la el însuș i (o astfel de muchie se numeș te buclă). Toate grafurile sunt împărț ite în două mari
grupuri: grafuri orientate ș i neorientate. Diferenț a este că muchiile din grafurile orientate,
graficele arc, au o direcț ie. Aceste tipuri de grafice au multe în comun între ele
alte, dar diferenț e semnificative sunt, de asemenea, prezente. Vom accentua ce fel de
grafurile sunt considerate în descrierea particulară a algoritmului. O muchie poate fi trasată ca un
linie. Dacă un graf este orientat, fiecare linie are o săgeată.
100
path (simple) ciclul (simplu)
Ultima definiț ie pe care o dăm aici este un graf ponderat. Grafuri se numesc ponderate, dacă fiecare
marginea este asociată cu un număr real, numit greutatea marginii. De exemplu, în drumul
exemplu de reț ea, greutatea fiecărei drum poate fi lungimea sa sau timpul minim necesar pentru
condu pe drum.
graf ponderat
Există mai multe moduri posibile de a reprezenta un graf în interiorul computerului. Vom
discută despre două dintre ele: matricea de adiacenț ă ș i lista de adiacenț ă.
a) Matrice de adiacenț ă
Fiecare celulă aijo matrice de adiacentă conț ine 0, dacă există o muchie între i-lea ș i j-lea
101
vârfuri ș i în alte cazuri. Înainte de a discuta despre avantajele ș i dezavantajele acestui
un fel de reprezentare, să vedem un exemplu.
Grafica prezentată de exemplu este nedirecț ionată. Asta înseamnă că matricea sa de adiacenț ă este
simetric. De fapt, în graf neorientat, dacă există o muchie (2, 5) atunci există ș i o
margine (5, 2). Aceasta este, de asemenea, motivul pentru care există două celule pentru fiecare margine în
exemplu. Buclele, dacă sunt permise într-un grafic, corespund elementelor diagonale ale
o matrice de adiacenț ă.
Avantaje. Matricea de adiacenț ă este foarte convenabilă pentru a lucra cu ea. Adăugaț i (eliminaț i) un
o margine poate fi realizată în O(1) timp, acelaș i timp este necesar pentru a verifica dacă există o margine
între două vârfuri. De asemenea, este foarte simplu de programat ș i în toate tutorialele noastre despre grafuri
vom lucra cu acest tip de reprezentare.
Dezavantaje.
Matricea de adiacen ț ă consumă o cantitate uria ș ă de memorie pentru stocarea graficelor mari.
Toate graficele pot fi împărț ite în două categorii, grafice sparse ș i grafice dense. Sparse
ones conț in nu prea multe margini (numărul de margini este mult mai mic decât pătratul de)
numărul de vârfuri, |E| << |V| 2). Pe de altă parte, grafurile dense con ț in
numărul de muchii comparabil cu pătratul numărului de vârfuri. Adiacenț ă
matricea este optimă pentru grafice dense, dar pentru cele rare este superfluă.
Următoarea dezavantajă a matricei de adiacen ț ă este că în multe algoritmi trebuie să
cunoaș te marginile, adiacente vârfului curent. Pentru a scoate în evidenț ă astfel de informaț ii
din matricea de adiacenț ă trebuie să scanezi peste linia corespunzătoare, care
rezultate cu o complexitate de O(|V|). Pentru algoritmi precum DFS sau bazaț i pe acesta, utilizarea de
matricea de adiacenț ă rezultă într-o complexitate generală de O(|V| 2), în timp ce poate fi
reducerea la O(|V| + |E|), când se foloseș te lista de adiacenț ă.
Ultimul dezavantaj, la care vrem să vă atragem aten ț ia, este că adiacen ț a
matricea necesită eforturi mari pentru adăugarea/eliminarea unui vârf. În cazul în care, un graf este
102
folosit doar pentru analiză, nu este necesar, dar dacă vrei să construieș ti complet
structură dinamică, utilizarea matricei de adiacenț ă o face destul de lentă pentru grafuri mari.
Pe scurt, matricea de adiacenț ă este o soluț ie bună pentru graficele dense, ceea ce implică să aibă
număr constant de vârfuri.
Această formă de reprezentare a grafului este una dintre alternativele la matricea de adiacenț ă.
necesită o cantitate mai mică de memorie ș i, în situa ț ii particulare, chiar poate depă ș i
matrice de adiacenț ă. Pentru fiecare vârf, lista de adiacenț ă stochează o listă de vârfuri, care sunt
adjacent to current one. Let us see an example.
1 4
2 4 5
3 5
4 2 5
Avantaje. Lista adiacentă ne permite să stocăm graful într-o formă mai compactă decât
matrice de adiacenț ă, dar diferenț a scade pe măsură ce un graf devine mai dens. Următorul
avantajul este că lista adjacentă permite obț inerea listei de vârfuri adiacente în timp O(1),
care este un mare avantaj pentru unele algoritmi.
Dezavantaje.
Adăugarea/îndepărtarea unei muchii din lista de adiacen ț ă nu este atât de u ș oară ca pentru adiacen ț ă.
matrice. Necesită, în medie, O(|E| / |V|) timp, ceea ce poate duce la cubic.
complexitate pentru grafuri dense pentru a adăuga toate muchiile.
•Verificarea, dacă există o muchie între două vârfuri se poate face în O(|E| / |V|) atunci când
lista vârfului adiacente este neordonată sau O(log2(|E| / |V|)) atunci când este sortat. Acest
operaț ia rămâne destul de ieftină.
103
•Lista adiacentă nu ne permite să facem o implementare eficientă, dacă este dinamică.
schimbarea numărului de vârfuri este necesară. Adăugarea unui nou vârf poate fi făcută în O(V),
dar eliminarea rezultă într-o complexitate O(E).
Concluzie: Lista de adiacenț ă este o soluț ie bună pentru grafuri rare ș i ne permite să facem modificări.
numărul de vârfuri mai eficient, decât dacă ar folosi o matrice de adiacenț ă. Dar totuș i există
soluț ii mai bune pentru a stoca grafuri complet dinamice.
Algoritm
Algoritm: Parcurgerea DFS(G)
//Implementaț i o traversare în adâncime a unui graf
Graf G=<V,E>
Graf G cu vârfurile sale marcate cu numere întregi consecutive în ordinea în care au
a fost întâlnit pentru prima dată de traversarea DFS
Marchează fiecare vârf în V cu 0 ca marcaj al stării „nevizitat”
Numără 0
Pentru fiecare vârf v în V face
Dacă v este marcat cu 0
dfs(v)
//sfârș it explorare DFS
Rutina
dfs (v)
//vizitează recursiv toate vârfurile nevizitate conectate la vârful v ș i le alocă
numerele în ordinea în care sunt întâmpinate prin variabila globală count
Numără Numără+1
Marchează v cu numărătoarea
Pentru fiecare vârf w din V adiacent lui v, fă
104
Dacă w este marcat cu 0
Dfs(w)
//sfârș it dfs
În DFS, fiecare vârf are trei culori posibile care reprezintă starea sa:
Notă. Pentru majoritatea algoritmilor, clasificarea booleană nevizitat / vizitat este suficientă, dar
aratăm cazul general aici.
Iniț ial, toate vârfurile sunt albe (nevizitate). DFS începe într-un vârf arbitrar ș i rulează ca
următoarele:
Exemplu: Parcurge ț i un graf prezentat mai jos, folosind DFS. Începe ț i de la un vârf cu
numărul 1.
Graf sursă.
105
Marchează un vârf ca fiind gri.
106
Există oMuchie(4, 2)ș i vârful a2 este nevizitat.
Du-te acolo.
107
Marchează vârful5 ca fiind gri.
108
Nu există căi pentru a merge de la vârful 3. Marcheză-l
ca negru ș i să revină la vârful 5.
109
Nu mai sunt margini, adiacente cu
vertex2. Marcaț i-l ca negru ș i reveniț i la
vertex4.
110
Nu mai există margini, adiacente la
vertex1. Marchează-l ca negru. DFS s-a terminat.
După cum puteț i observa din exemplu, DFS nu trece prin toate muchiile. Vârfurile ș i
muchiile, pe care căutarea în adâncime le-a vizitat, sunt un arbore. Acest arbore conț ine toate vârfurile de
graful (dacă este conectat) ș i se numeș te arbore de acoperire al grafului. Acest arbore exact
corespunde apelurilor recursive ale DFS.
Dacă un grafic este deconectat, DFS nu va vizita toate vârfurile sale. Pentru detalii, vezi găsirea
algoritmul componentelor conectate.
Analiza complexităț ii
Presupuneț i că graful este conectat. Căutarea în adâncime vizitează fiecare vârf din graf ș i
verifică fiecare muchie a sa. Prin urmare, complexitatea DFS este O(V + E). A ș a cum a fost
aș a cum s-a menț ionat anterior, dacă o matrice de adiacenț ă este folosită pentru reprezentarea unui graf, atunci toate
margini, adiacente unui vârf nu pot fi găsite eficient, ceea ce duce la O(V2) complexitate.
Verifică-ț i progresul
1.4 SUMMARY:
Un graf poate fi reprezentat în două moduri, adică matricea de adiacenț ă ș i metoda listei de adiacenț ă.
111
Matricea de adiacenț ă este o soluț ie bună pentru grafuri dense, iar lista de adiacenț ă este bună pentru
graf rar
Căutarea în adâncime (DFS) este un algoritm pentru traversarea sau căutarea unui arbore, structură de arbore,
sau grafic. Se începe de la rădăcină (selectând un anumit nod ca rădăcină în cazul graficului) ș i
explorează cât mai departe posibil pe fiecare ramură înainte de a reveni.
1.15 KEYWORDS
Grafic: un grafic este o reprezentare abstractă a unui set de obiecte unde anumite perechi de
obiectele sunt conectate prin legături. Obiectele interconectate sunt reprezentate de
abstrac ț ii matematice numite vârfuri ș i legăturile care conectează unele perechi de
vârful sunt numite margini.
Digraful este un grafic cu direcț ii pe marginile sale.
1. 1.3.1
2. 1.2.
3. 1.2
1.7 EXERCI ȚII Ș I RĂSPUNSURI LA FINA UNITĂ ȚII
Matricea 1
16. a.) Scrie graficul echivalent pentru matricea de mai sus (adică matricea1).
b.) Reprezentaț i matricea1 sub formă de listă de adiacenț ă.
Answers: SEE
112
1. 1.3.1
2. 1.2
3. 1.1
113
114