Shkarko - bitbit.al

Download Report

Transcript Shkarko - bitbit.al

Algoritmet e Renditjes
Leksion 4
Renditja me Nderfutje
Renditja me nderfutje eshte nje algoritem efikas per te renditur nje
numer te vogel elementesh. Renditja me nderfutje vepron ne
menyre te ngjashme me menyren se si shume njerez zakonisht i
rendisin letrat:
– Fillojme me doren e majte boshe dhe letrat jane te
permbysura mbi tavoline.
– Me pas ne heqim nje leter nga tavolina dhe e vendosim ate
ne pozicionin e duhur ne doren e majte.
– Per te gjetur pozicionin e duhur per
nje leter, ne e krahasojme ate me
secilen prej letrave qe i kemi ne dore,
nga e djathta ne te majte.
– Ne çdo moment, letrat ne doren e
majte jane te renditura dhe keto letra
ishin fillimisht ne maje te stives se
letrave mbi tavoline.
Renditja me Nderfutje
INSERTION-SORT(A)
1 for j ← 2 to length[A] do
2
key ← A[j]
3
// Insert A[j] into the sorted sequence A[1.. j - 1].
4
i←j-1
5
while i > 0 and A[i] > key do
6
A[i + 1] ← A[i]
7
i←i-1
8
A[i + 1] ← key
Renditja me Nderfutje
Pseudokodi per renditjen me nderfutje paraqitet si nje
procedure e quajtur INSERTION-SORT, e cila merr si nje
parameter nje vektor A[1..n] qe permban nje sekuence me
gjatesi n qe duhet renditur. (Ne kod numri n i elementeve ne A
paraqitet nga length[A].)
Ne çdo hap numrat input jane te renditur ne vend: numrat
zhvendosen brenda vektorit A, me te shumten nje numer
konstant te tyre te ruajtur jashte vektorit. Vektori input A
permban sekuencen output te renditur kur perfundon
procedura INSERTION-SORT.
Shembull 1: Renditja me Nderfutje
Shembull 2: Renditja me Nderfutje
Shembull mbi renditjen me nderfutje
9
4
3
7
6
5
8
Bashkesia origjinale me 7 numra te
plote pozitive.
4
9
3
7
6
5
8
Pjesa e hijezuar e renditur dhe
perpiqemi te nderfusim vleren 3
3
4
9
7
6
5
8
Pjesa e hijezuar e renditur dhe
perpiqemi te nderfusim vleren 7
3
4
7
9
6
5
8
Pjesa e hijezuar e renditur dhe
perpiqemi te nderfusim vleren 6
3
4
6
7
9
5
8
Pjesa e hijezuar e renditur dhe
perpiqemi te nderfusim vleren 5
3
4
5
6
7
9
8
Pjesa e hijezuar e renditur dhe
perpiqemi te nderfusim vleren 8
3
4
5
6
7
8
9
Bashkesia e vlerave e renditur ne rendin
rrites
Saktesia e Algoritmit - Invarianti
• Zakonisht ne perdorim nje invariant te ciklit per te na
ndihmuar te kuptojme pse nje algoritem jep pergjigjen
e sakte.
• Invarianti i Ciklit: Ne fillim te çdo iteracioni te ciklit “te
jashtem” for (ciklit te indeksuat nga j), nenvektori A[1 . . j −1]
perbehet nga elementet qe ndodheshin fillimisht ne A[1 . . j −
1] por te renditur ne rendin rrites.
Saktesia e Algoritmit - Invarianti
Per te perdorur nje invariant cikli ne menyre qe te vertetojme
saktesine, duhet te tregojme 3 gjera rreth tij:
• Inicializimi: Invarianti eshte i vertete perpara iteracionit te
pare te ciklit.
• Mirembajtja: Nese eshte i vertete perpara nje iteracioni te
ciklit, ai mbetet i vertete perpara iteracionit pasardhes te tij.
• Perfundimi: Kur cikli mbaron, invarianti, zakonisht se bashku
me arsyen se cikli mbaroi, na jep nje veçori qe ndihmon te
tregojme qe algoritmi eshte i sakte.
Saktesia e Algoritmit - Invarianti
Perdorimi i invariantit te ciklit eshte si induksioni matematik:
• Per te vertetuar qe nje veçori ruhet, ju vertetoni nje rast
baze dhe nje hap induktiv.
• Vertetimi qe invarianti ruhet, perpara iteracionit te pare
eshte si rasti baze.
• Vertetimi qe invarianti ruhet nga njeri iteracion tek tjetri
eshte si hapi induktiv.
• Pjesa e perfundimit ndryshon nga perdorimi i zakonshem i
induksionit matematik, ne te cilin hapi induktiv perdoret
ne infinit. Ne e ndalojme “induksionin” kur cikli perfundon.
• Ne mund t’i vertetojme te tri pjeset ne çfaredolloj rendi.
Invarianti per Renditjen me Nderfutje
Inicializimi:
Perpara iteracionit te pare, j = 2. Nenvektori A[1 . . j − 1] eshte
elementi i vetem A[1], i cili eshte elementi qe ndodhej fillimisht ne A[1], dhe
ai eshte i renditur.
Mirembajtja:
Per te qene me preciz, neve na duhet te percaktojme dhe te
vertetojme nje invariant cikli per “ciklin e brendshem” – ciklin while.
Ne vend qe te gjejme nje invariant tjeter te ciklit, ne verejme qe blloku i
instruksioneve brenda ciklit while, vepron duke levizur A[ j − 1], A[ j − 2], A[ j
− 3], e keshtu me radhe, me nga nje pozicion djathtas derisa gjendet
pozicioni i sakte i çelesit (i cili ka vleren qe ndodhej fillimisht ne A[ j ]). Ne
kete moment, vlera e çelesit vendoset ne ate pozicion.
Perfundimi:
Cikli i jashtem perfundon kur j > n; kjo ndodh kur j =n+1.
Prandaj, j −1 = n. Duke zevendesuar j −1 me n ne invariantin e ciklit, kemi qe
nenvektori A[1 . . n] perbehet nga elementet fillestare te vektorit A[1 . . n] por
te renditur. Me fjale te tjera i gjithe vektori eshte i renditur!
Si e analizojme kohen e ekzekutimit te nje algoritmi?
Koha e ekzekutimit te algoritmit varet nga inputi.
• Renditja e 1000 numrave kerkon me shume kohe se
renditja e 3 numrave.
• Nje algoritem renditjeje mund te kerkoje sasi kohe te
ndryshme mbi dy inpute te se njejtes madhesi. Psh: do te
shohim renditja me nderfutje kerkon me pak kohe per te
renditur n elemente kur ato jane qe ne fillim te renditur,
sesa kur ato jane te renditur ne rendin e kundert.
– Rasti me i mire i renditjes me nderfutje:
vektori fillestar eshte i renditur
– Rasti me i keq i renditjes me nderfutje:
vektori fillestar eshte i renditur ne rendin e kundert
Madhesia e inputit
Madhesia e inputit: Varet nga problemi qe po
studiohet.
• Zakonisht eshte numri i elementeve ne input. Si psh:
madhesia n e vektorit qe po renditet.
• Por mund te jete edhe diçka tjeter. Psh: ne rastin e
shumezimit te dy numrave te plote, mund te jete numri
total i biteve ne te dy numrat.
• Mund te pershkruhet nga me shume se nje numer. Psh,
koha e ekzekutimit e algoritmeve mbi grafet, zakonisht
shprehet ne varesi te numrit te kulmeve dhe numrit te
harqeve te grafit qe jepet si input.
Koha e ekzekutimit
Per nje input te caktuar, koha e ekzekutimit, eshte numri i
veprimeve primitive (hapave) qe ekzekutohen.
• Na duhet te percaktojme hapat qe te jene te pavarur nga lloji i
makines.
• Verejme qe çdo rresht i pseudokodit kerkon nje sasi konstante kohe.
• Nje rresht mund te kerkoje sasi te ndryshme kohe ne krahasim me
nje rresht tjeter, por çdo ekzekutim i rreshtit i kerkon te njejten sasi
kohe ci .
• Kjo eshte e vertete nese supozojme se rreshti perbehet vetem nga
veprime primitive.
– Nese rreshti perbehet nga nje thirrje procedure, atehere thirrja e
procedures kerkon kohe konstante, por ekzekutimi i saj mund te
mos kerkoje nje kohe konstante.
– Pra nese rreshti nuk ka veprime primitive, atehere ai mund te
kerkoje me teper se koha konstante.
Analiza e Renditjes me Nderfutje
Analiza e Renditjes me Nderfutje
•
Supozojme se rreshti i j-te kerkon kohen e
ekzekutimit ci qe eshte konstante. (Meqe rreshti i
trete eshte koment, ai nuk kerkon kohe per t’u
ekzekutuar.)
• Per j = 2, 3, . . . , n, le te jete tj numri i hereve qe
ekzekutohet testi i ciklit while, per ate vlere te j-se.
• Vini re qe kur ekziston nje cikel for ose while (per
shkak te testit ne fillim te ciklit) testi ekzekutohet nje
here me shume se trupi i ciklit.
Analiza e Renditjes me Nderfutje
Koha e ekzekutimi varet nga vlerat e tj .
Analiza – Rasti me i mire
Rasti me i mire: vektori eshte i renditur qe ne fillim
• Te gjitha tj jane 1.
• Koha e ekzekutimit eshte:
T (n) mund te shprehet si an + b per konstantet a dhe b
(qe varet nga kostot e shprehjeve ci).
Pra T (n) eshte nje funksion linear i n-se.
Analiza – Rasti me i keq
Rasti me i keq: vektori eshte i renditur ne rend te
kundert
• Duhet te krahasojme key me te gjithe elementet ne te majte
te pozicionit te j-te -> krahasohet me j − 1 elemente.
• Meqe cikli while ekziston sepse i arrin vleren 0, ka nje test
shtese pas j − 1 testeve -> tj = j .
Analiza – Rasti me i keq
• Duke shenuar k=j-1 kemi:
• Pra koha e ekzekutimit te algoritmit eshte:
• Pra T (n) mund te shprehet si an2 + bn + c per
konstgantet a, b, c (qe perseri varen nga kostot e
shprehjeve) -> T (n) eshte nje funksion kuadratik i nse.
• Renditja me nderfutje eshte e rendit n2
Renditja me flluska
• Metoda e flluskave bazohet, edhe kjo, ne ndarjen e
bashkesise se vlerave ne dy nenbashkesi nga te cilat
ajo e djathta eshte e renditur dhe hap pas hapi asaj i
bashkangjitet majtas elementi me i madh i
nenbashkesise se majte.
• Kjo renditje shkemben ne menyre te perseritur
elementet fqinje qe nuk jane te renditur.
BUBBLESORT(A)
1 for i ← 1 to length[A] do
2
for j ← 2 to length[A] – i+1 do
3
if A[j] < A[j - 1]
4
then exchange A[j] ↔ A[j - 1]
Shembull – Renditja me flluska
Shembull mbi renditjen me flluska
9
4
3
7
6
5
8
Bashkesia origjinale me 7 numra te
plote pozitive.
4
3
7
6
5
8
9
Pjesa e hijezuar e renditur dhe
perpiqemi te bashkangjisim vleren 8
3
4
6
5
7
8
9
Pjesa e hijezuar e renditur dhe
perpiqemi te bashkangjisim vleren 7
3
4
5
6
7
8
9
Pjesa e hijezuar e renditur dhe
perpiqemi te bashkangjisim vleren 6
3
4
5
6
7
8
9
Pjesa e hijezuar e renditur dhe
perpiqemi te bashkangjisim vleren 5
3
4
5
6
7
8
9
Pjesa e hijezuar e renditur dhe
perpiqemi te bashkangjisim vleren 4
3
4
5
6
7
8
9
Bashkesia e vlerave e renditur ne rendin
rrites
Renditja me flluska
BUBBLESORT(A)
1 for i ← 1 to length[A] do
2
for j ← 2 to length[A] – i+1 do
3
if A[j] < A[j - 1]
4
then exchange A[j] ↔ A[j - 1]
Cikli i pare ne algoritem realizon bredhjen neper
bashkesi.
Cikli i dyte zhvendos, me ane te shkembimeve te
njepasnjeshme (nga ku emri flluska), elementin me
te madh te nenbashkesise se parenditur te majte deri
tek nje element perpara nenbashkesise se renditur te
djathte
Analiza - Renditja me flluska
• Algoritmi permban dy cikle te perfshira.
• Cikli i pare for i := 1 to n do ekzekuton n here ciklin e
dyte for j := 2 to n-i+1 do (ku n eshte gjatesia e
vektorit -> length[A])
• Po te analizojme ciklin e dyte rezulton se ai ekzekutohet
n-i+1 here ose ne menyre te detajuar:
– heren e pare n-1+1-1=n-1 here;
– heren e dyte n-2+1-1=n-2 here e keshtu me rradhe
heren e fundit 1 here.
– Pra ne finale kemi n-1 +n-2 + ….. + 1 perseritje ose
e shprehur ndryshe (progresion aritmetik) kemi
(n-1)*(n-2)/2 perseritje.
– Duke shfrytezuar vetite e njohura te kompleksitetit
arrijme ne konkluzionin se algoritmi ne shqyrtim
eshte i rendit O(n2).
Krahasimi: Renditja me nderfutje dhe
Renditja me flluska
• Nga analiza e efikasitetit te dy algoritmeve qe sapo
pame, veme re se algoritmi i renditjes me flluska eshte i
te njejtit rend me ate te renditjes me nderfutje.
• Sidoqofte, kjo nuk do te thote se per ne aata jane
njelloj te preferueshem.
• Ne algoritmin e renditjes me flluska numri i
ekzekutimeve eshte i parapercaktuar, ndersa ne
algoritmin e renditjes me nderfutje numri i
ekzekutimeve eshte ne varesi te vendosjes se
elementeve.
• Si konkluzion, numri i ekzekutimeve ne algoritmin e
renditjes me nderfutje eshte <= me ate te
ekzekutimeve ne algoritmin e renditjes me flluska por
rendi i tyre eshte i njejte.
Shembuj te algoritmeve te renditjes
Shembuj te algoritmeve te renditjes ne menyre te
animuar i gjeni ne adresen e meposhtme:
http://math.hws.edu/TMCM/java/x
SortLab/index.html
Detyre Shtepie
• Bazuar ne algoritmet ne pseudokod per renditjen me
nderfutje dhe ate me flluska, ndertoni nga nje
program ne Paskal per keto algoritme.
• Modifikojini algoritmet e mesiperme ne menyre qe
ato t’i rendisin vektoret ne rendin zbrites.
Pyetje