This is an old revision of the document!
Tema constă în definirea și utilizarea heap-urilor de împerechere și este împărțită în 4 etape:
Așa cum se poate observa, ziua deadline-ului variază în funcție de semigrupa în care sunteți repartizați. Restanțierii care refac tema și nu refac laboratorul beneficiază de ultimul deadline (deci vor avea deadline-uri în zilele de 14.03, 21.03, 28.03, 04.04).
Rezolvările tuturor etapelor pot fi trimise până în ziua laboratorului 6, dar orice exercițiu trimis după deadline (și până în ziua laboratorului 6) se punctează cu jumătate din punctaj. Orice exercițiu trimis după ziua laboratorului 6 nu se mai punctează deloc. Nota finală pe etapă se calculează conform formulei: n = (n1 + n2) / 2 (n1 = nota obținută înainte de deadline; n2 = nota obținută după deadline). Când toate submisiile sunt înainte de deadline, nota pe ultima submisie este și nota finală (întrucât n1 = n2).
În fiecare etapă, veți folosi ce ați învățat în săptămâna anterioară pentru a dezvolta aplicația.
Pentru fiecare etapă veți primi un schelet de cod (dar rezolvarea se bazează în mare măsură pe rezolvările anterioare). Enunțul din această pagină este menit să descrie heap-urile de împerechere (pe care le vom numi PH, conform prescurtării termenului englez “pairing heap”) și să vină cu exemple de rulare a funcțiilor mai complexe din schelet. Dacă preferați, puteți rezolva tema utilizând doar indicațiile din schelet.
În prima etapă vă veți familiariza cu structura și reprezentarea heap-urilor de împerechere (PH) în Racket, și veți implementa un max-heap de împerechere împreună cu operațiile sale uzuale.
Un PH este un heap n
-ar eficient și simplu de implementat. În Racket, vom reprezenta un PH vid ca pe o listă vidă, iar un PH nevid ca pe o listă de n
elemente, primul element fiind valoarea din rădăcină, iar următoarele n-1
elemente fiind PH-uri - fiii nodului rădăcină. Veți implementa următorii constructori și operatori ai acestui tip:
empty-ph
: creează un PH vid(val->ph val)
: creează un PH care este un singur nod cu valoarea val(ph-empty? ph)
: verifică dacă un PH este vid(ph-root ph)
: întoarce valoarea din rădăcină, sau false dacă nu există o asemenea valoare întrucât argumentul este un PH vid(ph-subtrees ph)
: întoarce lista fiilor rădăcinii (o listă de PH-uri), sau false dacă argumentul este un PH vid(merge ph1 ph2)
: reunește PH-urile ph1 și ph2 - în cazul unui max-PH, aceasta înseamnă că PH-ul cu rădăcina mai mică devine cel mai din stânga fiu al celui cu rădăcina mai mare, ca în figura de mai jos: (merge '(8 (2) (5) (7 (3))) '(12 (6) (11 (8) (10 (4) (1) (2)))))
12 > 8
, primul arbore devine cel mai din stânga fiu al celui de-al doilea, producând rezultatul '(12 (8 (2) (5) (7 (3))) (6) (11 (8) (10 (4) (1) (2))))
(list->ph lst)
: inserează toate valorile din lista lst, de la dreapta la stânga, într-un PH vid(list->ph '(2 5 8 7 3))
'(3)
'(7 (3))
'(8 (7 (3)))
'(8 (5) (7 (3)))
'(8 (2) (5) (7 (3)))
(two-pass-merge-LR phs)
: reunește toate PH-urile din lista phs, conform unui protocol în 2 pași, ca în figura de mai jos: (two-pass-merge-LR '((8 (2)) (12) (14 (11 (8))) (5 (4)) (11 (10 (9)))))
'(12 (8 (2)))
'(14 (5 (4)) (11 (8)))
'(11 (10 (9)))
(ultima valoare rămâne ca atare, întrucât nu are cu cine să se unească)'(14 (12 (8 (2))) (5 (4)) (11 (8)))
⇒ '(14 (11 (10 (9))) (12 (8 (2))) (5 (4)) (11 (8)))
(two-pass-merge-RL phs)
: la fel, însă ambii pași se realizează de la dreapta la stânga(two-pass-merge-RL '((8 (2)) (12) (14 (11 (8))) (5 (4)) (11 (10 (9)))))
'(8 (2))
, '(14 (12) (11 (8)))
, '(11 (5 (4)) (10 (9)))
(prima valoare rămâne ca atare, întrucât nu are cu cine să se unească)'(14 (11 (5 (4)) (10 (9))) (12) (11 (8)))
⇒ '(14 (8 (2)) (11 (5 (4)) (10 (9))) (12) (11 (8)))
(tournament-merge phs)
: reprezintă un alt protocol de reuniune a PH-urilor din lista phs - se realizează primul pas de la two-pass-merge-LR asupra listei phs, apoi din nou asupra listei rezultate anterior, și tot așa până rămâne un singur PH(tournament-merge '((8 (2)) (12) (14 (11 (8))) (5 (4)) (11 (10 (9)))))
'(12 (8 (2)))
, '(14 (5 (4)) (11 (8)))
, '(11 (10 (9)))
(ca la two-pass-merge-LR)'(14 (12 (8 (2))) (5 (4)) (11 (8)))
, '(11 (10 (9)))
'(14 (11 (10 (9))) (12 (8 (2))) (5 (4)) (11 (8)))
(ph-del-root ph)
: întoarce PH-ul obținut în urma ștergerii rădăcinii lui ph - fiii nodului șters sunt reuniți prin two-pass-merge-LR (vezi figura anterioară)În rezolvare, veți exersa lucrul cu:
Unele exerciții vă cer să folosiți un anumit tip de recursivitate. Fiecare restricție încălcată atrage după sine o depunctare de 10p.