190 likes | 313 Views
Dziedziczenie (cd.). Reguła konkatenacji II przykład - heapsort Reguła konkatenacji III. Reguła konkatenacji II - inner.
E N D
Dziedziczenie (cd.) Reguła konkatenacji II przykład - heapsort Reguła konkatenacji III Regula konkatenacji II
Reguła konkatenacji II - inner • Prawda o dziedziczeniu jest bardziej skomplikowana niż mogłoby to wyglądać po poprzednim wykładzie. Rozpatrzmy znany już nam przykład z klasami: rachunek, rachunek_za_elektryczność, …Spróbujmy wydrukować rachunek podczas jego tworzenia Regula konkatenacji II
unit bill: class(who: person, day: date); var amount: integer, is_paid: Boolean; beginwriteln(«Rachunek z dnia», day); writeln(«Dla Pani/Pana», who); writeln(«kwota do zapłacenia=», amount) end bill; a teraz klasa rachunek_za_elektryczność. unit electricity_bill: bill class(kWh: integer); begin amount := kWh * price_kWh; end electricity_bill; i klasa rachunek_za_gaz unit gaz_bill: bill class(cubicmeters: integer); begin amount := cubicmeters * price_gaz; end gaz_bill; Jak wydrukować niezerową kwotę? Jak uniknąć powtarzania trzeciej instrukcji writeln w podklasach? Regula konkatenacji II
To słowo kluczowe może wystąpić w klasie dziedziczonej wszędzie tam, gdzie możemy napisać instrukcję. • Osiągniemy to stosując pseudoinstrukcję inner. • Podczas dziedziczenia-składania modułów słowo inner będzie zastąpione instrukcjami klasy dziedziczonej. • Inner występuje tylko raz w module klasy, domyślnie na końcu ciągu instrukcji. Regula konkatenacji II
Reguła konkatenacji II • Poniższa tabelka prezentuje ideę użycia pseudoinstrukcji inner. • Należy pamiętać, że słowo inner nie musi- dzielić ciągu instrukcji na prolog i epilog (chociaż jest tak często używane),- może wystąpić wewnątrz instrukcji while lub if ... Regula konkatenacji II
Przykład Zaprogramujmy algorytm sortowania stogowego - heapsort unit heapsort: procedure(A: arrayof integer); Przypomnijmy, że stóg możemy reprezentować jako tablicę. Korzeniem stogu jest element A[1]. Synami elementu A[i] są A[2*i] (lewy syn) i A[2*i+1] (prawy syn), o ile istnieją tzn. mieszczą się w tablicy A. Takie drzewo jest binarne i doskonałe. Dana tablica A nie musi być jednak stogiem, tzn. nie wiemy czy spełnia warunek A[i] < A[2*i] i A[i] < A[2*i+1]. Algorytm heapsort sprowadza się do dwu poleceń: kopcuj - tzn. zbuduj kopiec z elementów tablicy A, stosując relację > zamiast <. Tak by korzeń był maksimum sortuj - wstawiając korzeń na koniec i kopcując od nowa. Regula konkatenacji II
Struktura procedury unit heapsort: procedure(A: arrayof integer);varunit kopcuj: procedure; …unit sortuj: procedure; ...Beginp := upperA); l := upper(A)div2 +1;call kopcuj;call sortuj; end heapsort; Regula konkatenacji II
Idea algorytmu kopcuj:zauważmy, że w drugiej połowie tablicy A są liście, i że tworzą one las stogów,nasz algorytm będzie dołaczać do tego lasu kolejno elementy A[n/2 -1], A[n/2 -2], … , A[1], w taki sposób by zachować wlasność: elementy A[i],A[i+1], …, A[n] tworzą las stogów. Dopóki nie dołaczono elementu A[1] powtarzaj do ciągu A[i],A[i+1], … , A[n] stanowiącego las stogów dołącz element A[i-1] i w razie potrzeby spraw by ciąg elementów A[i-1],A[i], … , A[n] był znowu lasem stogów. Zaprogramujmy ten krok wewnątrz pętli dopóki. Regula konkatenacji II
Załóżmy, że elementy A[l+1], … , A[n]stanowią las stogów.Niech i=l. Dołączamy element A[i]. Jeśli 2*i+1 < n, to istnieją obaj synowie tego elementu (A[2*i] i A[2*i+1]). Jeżeli przy tym obaj są mniejsi od A[i] to nic nie trzeba robić bo są (z założenia) korzeniami dwu stogów. Jeśli jeden z nich jest większy od A[i] to trzeba dokonać poprawy, w tym celu: a) wybieramy większego z dwu synów i zamieniamy jego wartośc z A[i],b) powtarzamy badanie dla odpowiedniego elementu A[2*i] (lub A[2*i+1]) aż do osiągnięcia pewności, że również oba poddrzewa węzła o numerze i-1 są stogami. Regula konkatenacji II
A oto kod tego algorytmu: i:=l; j:= 2*i; x := A[i];while{istnieje syn} do {A[j] jest większym z synów} if x >= A[j]then exit {już dobrze}fi; A[i] := A[j]; i := j; j:= 2*i;od; A[i] := x; {odłożone w czasie. Ale zdążyliśmy!} Regula konkatenacji II
A oto kod tego algorytmu: j:= 2*i; x := A[i];while j<= n {istnieje syn} do if j<n andif A[j]< A[j+1] then j:=j+1 fi;{A[j] jest większym z synów} if x >= A[j]then exit {już dobrze}fi; A[i] := A[j]; i := j; j:= 2*i;od; A[i] := x; {odłożone w czasie. Ale zdążyliśmy!} Nazwijmy go przesiewanie. Regula konkatenacji II
Napiszmy teraz procedurę kopcuj unit kopcuj: procedure;begin l:=(upper(A)div2)+1;do l:=l=1;if l=lower(A) then exit fi;{tu wpisujemy przesiewanie }odend kopcuj; Regula konkatenacji II
A teraz napiszmy procedurę sortuj unit sortuj: procedure;beginp := upper(A);do x :=A(lower(A)); A(lower(A):=A[p]; A[p]:=x; p:=p-1; if p=lowe(A)then exit fi;{tu wpisujemy przesiewanie } odend sortuj; Regula konkatenacji II
Łatwo zauważyć, że obie procedury mają część wspólną.Można to wykorzystać i napisać procedurę przesiewanie, która będzie wywoływana z obu procedur: kopcuj i sortuj.My jednak wykorzystamy dziedziczenie i stworzymy klasę przesiewanie, a procedury kopcuj i sortuj będą ją dziedziczyć. Regula konkatenacji II
unit przesiewanie: class; var koniec: Boolean;begindo inner;if koniec then exit fi; i:=l; j:=2*i; x := A[i];while do if j<p andif A[j]<A[j+1]then j:=j+1 fi; if then exit fi; A[i]:=A[j]; i :=j; j := 2*i; od; A[i] := x; odend przesiewanie; Regula konkatenacji II
Nowa wersja procedury heapsort wygląda tak: Unit heapsort:procedure(A:arrayof integer);var i, j, l, p, x: integer; unit przesiewanie: class; … unit kopcuj: przesiewanie procedure; beginkoniec:= l=lower(A); l:=l-1; end kopcuj;unit sortuj: procedure;beginkoniec:=p=lower(A); x:=lower(A); A[lower(A)]:=A[p]; A[p]:=x; p:=p=1; end sortuj;beginl:=upper(A) div 2 +1; p:=upper(A);call kopcuj;call sortuj;end heapsort; Regula konkatenacji II
Podsumowanie • Poznaliśmy lepiej regułę konkatenacji, • Nauczyliśmy się wykorzystywać dziedziczenie do “wyciagania części wspólnej algorytmu przed nawias” • Zobaczymy później jak tworzyć algorytmy abstrakcyjne posługując się dziedziczeniem i inner. Regula konkatenacji II
Zadanie:Napisać dwie wersje procedury heapsort i dokonać pomiarów czasu wykonania w celu porównania funkcji kosztu tych dwu algorytmów. • Pytania: • czy można osiągnąć taki efekt w C++? • czy można osiągnąć taki efekt w Javie? Regula konkatenacji II