Metody programowania / Ćwiczenia 2: Różnice pomiędzy wersjami
(8 zadan na listy) |
|||
Linia 83: | Linia 83: | ||
dispose(atrapa); | dispose(atrapa); | ||
'''end'''; | '''end'''; | ||
− | ''Koszt czasowy'': liniowy względem sumy długości | + | ''Koszt czasowy'': liniowy względem sumy długości list |
''Koszt pamięciowy'': stały | ''Koszt pamięciowy'': stały | ||
Linia 91: | Linia 91: | ||
{{cwiczenie| 1|pytanko 1|<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | {{cwiczenie| 1|pytanko 1|<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
Czy instrukcja atrapa^.nast:=nil jest potrzebna? W jakich przypadkach ? | Czy instrukcja atrapa^.nast:=nil jest potrzebna? W jakich przypadkach ? | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | == Zadanie 3 (Usuwanie elementów zadanych listą)== | ||
+ | Napisz procedurę Usuń(var l1:lista; l2:lista) która usunie z listy l1 wszystkie elementy z listy l2. Zakładamy, że listy l1 i l2 są posortowanych niemalejąco. | ||
+ | |||
+ | {{rozwiazanie| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | '''procedure''' Usuń(var l1:lista; l2:lista); | ||
+ | //Usuwamy z listy l1 wszystkie elementy z listy l2; zakładamy, że listy l1 i l2 są posortowanych niemalejąco | ||
+ | '''var''' atrapa, poprz: lista; | ||
+ | '''begin''' | ||
+ | new(atrapa); | ||
+ | atrapa^.nast:=l1; | ||
+ | poprz:=atrapa; | ||
+ | '''while''' l1 <> nil and l2 <> nil '''do''' | ||
+ | '''if''' l1^.nast < l2^.nast '''then''' '''begin''' | ||
+ | l1:=l1^.nast; | ||
+ | poprz:=poprz^.nast; | ||
+ | '''end''' | ||
+ | '''else''' | ||
+ | '''if''' l1^.nast > l2^.nast '''then''' | ||
+ | l2:=l2^.nast | ||
+ | '''else''' '''begin''' | ||
+ | poprz^.nast:=l1^.nast; | ||
+ | dispose(l1); | ||
+ | l1:=poprz^.nast; | ||
+ | '''end'''; | ||
+ | l1:=atrapa^.nast; | ||
+ | dispose(atrapa); | ||
+ | '''end'''; | ||
+ | ''Koszt czasowy'': liniowy względem sumy długości list | ||
+ | |||
+ | ''Koszt pamięciowy'': stały | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | {{cwiczenie| 1|pytanko 1|<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | Czy lista l1 musi być przekazywana przez zmienną ? W jakich przypadkach to się przydaje ? | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | == Zadanie 4 (Uporządkowanie elementów w liście)== | ||
+ | Napisz procedurę Uporządkuj(var l:lista) która przestawi elementy w liście l tak by najpierw były elementy w których pole w jest ujemne, potem równe zero a potem dodatnie. Dodatkowo względna kolejność elelmentów jednego rodzaju (dodatnich, równych zero i ujemnych) powinna być zachowana. | ||
+ | |||
+ | |||
+ | {{rozwiazanie| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | '''procedure''' Uporządkuj(var l:lista); | ||
+ | //Ustawiamy elementy listy l tak by najpierw były elemnty ujemne, potem równe zero, a na końcu dodatnie | ||
+ | '''var''' atrapau, atrapaz, atrapad, u, z, d : lista; | ||
+ | '''begin''' | ||
+ | new(atrapau); u:=atrapau; | ||
+ | new(atrapaz); z:=atrapaz; | ||
+ | new(atrapad); d:=atrapad; | ||
+ | '''while''' l <> nil '''do''' '''begin''' | ||
+ | '''if''' l^.w < 0 '''then''' '''begin''' | ||
+ | u^.nast:=l; | ||
+ | u:=u^.nast; | ||
+ | '''end''' | ||
+ | '''else''' | ||
+ | '''if''' l^.w = 0 '''then''' '''begin''' | ||
+ | z^.nast:=l; | ||
+ | z:=z^.nast; | ||
+ | '''end''' | ||
+ | '''else''' '''begin''' | ||
+ | d^.nast:=l; | ||
+ | d:=d^.nast; | ||
+ | '''end'''; | ||
+ | d.^nast:=nil; | ||
+ | z^.nast:=atrapad^.nast; | ||
+ | u^.nast:=atrapaz^.nast; | ||
+ | l:=atrapau^.nast; | ||
+ | dispose(atrapad); | ||
+ | dispose(atrapaz); | ||
+ | dispose(atrapau); | ||
+ | '''end'''; | ||
+ | ''Koszt czasowy'': liniowy względem długości listy | ||
+ | |||
+ | ''Koszt pamięciowy'': stały | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | |||
+ | == Zadanie 5 (Problem Józefa Flawiusza)== | ||
+ | Napisz procedurę Flawiusz(var l:lista; k:integer), która dla danego | ||
+ | k > 0 i niepustej cyklicznej listy l, cyklicznie usuwa co k-ty element listy, tak aby pozostał tylko jeden. Liczenie rozpoczynamy od elemnetu wskazywanego przez l. | ||
+ | |||
+ | |||
+ | {{rozwiazanie| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | '''procedure''' Flawiusz(var l:lista; k:integer); | ||
+ | //Usuwamy z listy l cyklicznie co k-ty element dopóki nie zostanie 1; k>0, l niepusta cykliczna | ||
+ | '''var''' atrapa, poprz: lista; | ||
+ | '''begin''' | ||
+ | poprz:=l^.nast; | ||
+ | '''while''' poprz^.nast <> poprz '''do''' poprz:=poprz.^nast; | ||
+ | '''while''' poprz <> poprz^.nast '''do''' '''begin''' | ||
+ | '''for''' i:=1 '''to''' k-1 '''do''' '''begin''' poprz:=poprz^.nast; | ||
+ | pom:=poprz^.nast; | ||
+ | poprz^.nast:=pom^.nast; | ||
+ | dispose(pom); | ||
+ | '''end'''; | ||
+ | l:=poprz; | ||
+ | '''end'''; | ||
+ | ''Koszt czasowy'': rzędu n*k, gdzie n to długość listy | ||
+ | |||
+ | ''Koszt pamięciowy'': stały | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | == Zadanie 6 (Listy łączące się)== | ||
+ | Dane są dwie listy proste (kończące się nilami). Napisz funkcję stwierdzającą czy te listy mają jakiś wspólny element (nie wartość typu integer, a element typu el_listy). | ||
+ | |||
+ | {{wskazowka| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | Jeśli listy mają wspólny element to ostatni niepusty element l1 i ostatni niepusty element l2 muszą byc takie same. | ||
+ | </div> | ||
+ | </div> | ||
+ | }} | ||
+ | |||
+ | {{rozwiazanie| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | '''function''' Wspólny(l1, l2:lista):boolean; | ||
+ | //Sprawdzamy czy listy proste l1 i l2 maja wspólny element | ||
+ | '''var''' pom1, pom2: lista; | ||
+ | '''begin''' | ||
+ | '''if''' l1=nil '''or''' l2=nil '''then''' Wspólny:=false | ||
+ | '''else''' '''begin''' | ||
+ | pom1:=l1; | ||
+ | '''while''' pom1^.nast <> nil '''do''' pom1:=pom1.^nast; | ||
+ | pom2:=l2; | ||
+ | '''while''' pom2^.nast <> nil '''do''' pom2:=pom2.^nast; | ||
+ | Wspólny:=(pom1=pom2); | ||
+ | '''end'''; | ||
+ | '''end'''; | ||
+ | ''Koszt czasowy'': liniowy względem sumy długości list | ||
+ | |||
+ | ''Koszt pamięciowy'': stały | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | == Zadanie 7 (Pierwszy wspólny element list łączących się)== | ||
+ | Dane są dwie listy proste (kończące się nilami) i takie że maja one element wspólny (funkcja Wspólny z poprzedniego zadania dałaby wynik true). Napisz funkcję odnajdującą pierwszy element wspólny tych list. | ||
+ | |||
+ | {{wskazowka| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | Pierwszy wspólny element jest tak samo odległy od końca list. Jeśli więc obliczymy długości list to możemy iść po nich równocześnie w takiej samej odległości od końca i sprawdzać czy trafiliśmy już na wspolny element czy nie. | ||
+ | </div> | ||
+ | </div> | ||
+ | }} | ||
+ | |||
+ | {{rozwiazanie| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | '''function''' PierwszyWspólny(l1, l2:lista):lista; | ||
+ | //Listy l1 i l2 maja wspólny element; szukamy pierwszego elementu wspólnego tych list | ||
+ | '''var''' dl1, dl2, i: integer; | ||
+ | pom1, pom2: lista; | ||
+ | '''begin''' | ||
+ | dl1:=0; pom1:=l1; | ||
+ | '''while''' pom1 <> nil '''do''' '''begin''' | ||
+ | dl1:=dl1+1; | ||
+ | pom1:=pom1^.nast; | ||
+ | '''end'''; | ||
+ | dl2:=0; pom2:=l2; | ||
+ | '''while''' pom2 <> nil '''do''' '''begin''' | ||
+ | dl2:=dl2+1; | ||
+ | pom2:=pom2^.nast; | ||
+ | '''end'''; | ||
+ | '''for''' i:=1 '''to''' dl1-dl2 '''do''' l1:=l1^.nast; | ||
+ | '''for''' i:=1 '''to''' dl2-dl1 '''do''' l2:=l2^.nast; | ||
+ | '''while''' l1 <> l2 '''do''' '''begin''' | ||
+ | l1:=l1^.nast; | ||
+ | l2:=l2^.nast; | ||
+ | '''end'''; | ||
+ | PierwszyWspólny:=l1; | ||
+ | '''end'''; | ||
+ | ''Koszt czasowy'': liniowy względem sumy długości list | ||
+ | |||
+ | ''Koszt pamięciowy'': stały | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | {{cwiczenie| 1|pytanko 1|<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | Skąd wiadomo, że w ostatnim while'u l1 i l2 sa zawsze różne od nil ? | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | == Zadanie 8 (Listy z cyklem)== | ||
+ | Napisz funkcje która sprawdzi czy dana l typu lista jest listą prostą czy też listą z cyklem. | ||
+ | |||
+ | {{wskazowka| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | Wystarczy poruszać sie po liście dwoma wskaźnikami o dwóch różnych względnie pierwszych prędkościach; wtedy albo trafimy na nil albo te wskaźniki się zejdą. | ||
+ | </div> | ||
+ | </div> | ||
+ | }} | ||
+ | |||
+ | {{rozwiazanie| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | '''function''' ListaZCyklem(l:lista):boolean; | ||
+ | //Sprawdzamy czy lista l jest listą z cyklem, czy tez kończy sie nilem | ||
+ | '''var''' pom1, pom2: lista; | ||
+ | '''begin''' | ||
+ | pom1:=l; | ||
+ | pom2:=l^.nast; | ||
+ | '''while''' pom2 <> nil '''and''' pom2 <> pom1 '''do''' '''begin''' | ||
+ | pom1:=pom1^.nast; | ||
+ | pom2:=pom2^.nast; | ||
+ | if pom2 <> nil pom2:=pom2^.nast; | ||
+ | '''end'''; | ||
+ | ListaZCyklem:=(pom1=pom2); | ||
+ | '''end'''; | ||
+ | ''Koszt czasowy'': liniowy względem długości listy | ||
+ | |||
+ | ''Koszt pamięciowy'': stały | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | == Zadanie 8 (Długość cyklu w liście z cyklem)== | ||
+ | Napisz funkcje która dla danej listy z cyklem obliczy długość cyklu. | ||
+ | |||
+ | {{wskazowka| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | Można poruszać sie po liście dwoma wskaźnikami tak jak w zadaniu poprzednim; gdy wskaźniki sie zejdą to znaczyże jesteśmy na cyklu; wystarczy zatrzymać jeden wskaźnik a drugim obejść cykl. | ||
+ | </div> | ||
+ | </div> | ||
+ | }} | ||
+ | |||
+ | {{rozwiazanie| 1||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | '''function''' DługośćCyklu1(l:lista):boolean; | ||
+ | //Obliczamy długość cyklu dla listy z cyklem | ||
+ | '''var''' pom1, pom2: lista; | ||
+ | dl: integer; | ||
+ | '''begin''' | ||
+ | pom1:=l; | ||
+ | pom2:=l^.nast; | ||
+ | '''while''' pom2 <> pom1 '''do''' '''begin''' | ||
+ | pom1:=pom1^.nast; | ||
+ | pom2:=pom2^.nast; | ||
+ | pom2:=pom2^.nast; | ||
+ | '''end'''; | ||
+ | pom2:=pom1^.nast; | ||
+ | dl:=1; | ||
+ | '''while''' pom2 <> pom1 '''do''' '''begin''' | ||
+ | dl:=dl+1; | ||
+ | pom2:=pom2^.nast; | ||
+ | '''end'''; | ||
+ | DługośćCyklu1:=dl; | ||
+ | '''end'''; | ||
+ | ''Koszt czasowy'': liniowy względem długości listy | ||
+ | |||
+ | ''Koszt pamięciowy'': stały | ||
+ | </div> | ||
+ | </div>}} | ||
+ | |||
+ | {{wskazowka| 2||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | Jeśli przechodząc po liście z cyklem będziemy ją odwracać to dojdziemy do poczatku; odwiedzimy przy tym 2m+n elementów gdzie n to długosć cyklu a n to liczba elementów poza cyklem. Wtedy (2m+n div 2)-ty element leży na cyklu i poczynając od niego można policzyc długość cyklu. | ||
+ | </div> | ||
+ | </div> | ||
+ | }} | ||
+ | |||
+ | {{rozwiazanie| 2||<div class="mw-collapsible mw-made=collapsible mw-collapsed"><div class="mw-collapsible-content" style="display:none"> | ||
+ | '''function''' DługośćCyklu2(l:lista):boolean; | ||
+ | //Obliczamy długość cyklu dla listy z cyklem | ||
+ | '''var''' poprz, akt, pom1, pom2: lista; | ||
+ | dl: integer; | ||
+ | '''begin''' | ||
+ | poprz:=nil; | ||
+ | akt:=l; | ||
+ | dl:=0; | ||
+ | '''while''' akt <> nil '''do''' '''begin''' | ||
+ | pom1:=akt^.nast; | ||
+ | akt^.nast:=poprz; | ||
+ | poprz:=akt; | ||
+ | akt:=pom1; | ||
+ | dl:=dl+1; | ||
+ | '''end'''; | ||
+ | pom1:=l; //dl to 2m+n, gdzie n to długosć cyklu a n to liczba elementów poza cyklem | ||
+ | '''for''' i:=1 '''to''' (dl div 2) '''do''' pom1:=pom1^.nast; | ||
+ | pom2:=pom1^.nast; //pom1 i pom2 leżą na cyklu | ||
+ | dl:=1; //liczymy długość cyklu | ||
+ | '''while''' pom2 <> pom1 '''do''' '''begin''' | ||
+ | dl:=dl+1; | ||
+ | pom2:=pom2^.nast; | ||
+ | '''end'''; | ||
+ | DługośćCyklu2:=dl; | ||
+ | '''end'''; | ||
+ | ''Koszt czasowy'': liniowy względem długości listy | ||
+ | |||
+ | ''Koszt pamięciowy'': stały | ||
</div> | </div> | ||
</div>}} | </div>}} |
Wersja z 11:04, 10 sie 2006
To są zadania na listy.
W poniższych zadaniach będziemy używać następujących typów:
type el_listy=record w: integer; nast: ^el_listy; end; lista=^el_listy;
Zadanie 1 (Odwracanie listy)
Napisz procedurę Odwróć(var l:lista) odwracającą listę l.
Rozwiązanie 1
Ćwiczenie 1
Zadanie 2 (Scalanie dwóch posortowanych list)
Napisz funkcję Scal(l1,l2:lista):lista scalającą dwie posortowane niemalejąco listy l1 i l2, tak aby wynikowa lista równiez była posortowana niemalejąco.
Rozwiązanie 1
Ćwiczenie 1
Zadanie 3 (Usuwanie elementów zadanych listą)
Napisz procedurę Usuń(var l1:lista; l2:lista) która usunie z listy l1 wszystkie elementy z listy l2. Zakładamy, że listy l1 i l2 są posortowanych niemalejąco.
Rozwiązanie 1
Ćwiczenie 1
Zadanie 4 (Uporządkowanie elementów w liście)
Napisz procedurę Uporządkuj(var l:lista) która przestawi elementy w liście l tak by najpierw były elementy w których pole w jest ujemne, potem równe zero a potem dodatnie. Dodatkowo względna kolejność elelmentów jednego rodzaju (dodatnich, równych zero i ujemnych) powinna być zachowana.
Rozwiązanie 1
Zadanie 5 (Problem Józefa Flawiusza)
Napisz procedurę Flawiusz(var l:lista; k:integer), która dla danego k > 0 i niepustej cyklicznej listy l, cyklicznie usuwa co k-ty element listy, tak aby pozostał tylko jeden. Liczenie rozpoczynamy od elemnetu wskazywanego przez l.
Rozwiązanie 1
Zadanie 6 (Listy łączące się)
Dane są dwie listy proste (kończące się nilami). Napisz funkcję stwierdzającą czy te listy mają jakiś wspólny element (nie wartość typu integer, a element typu el_listy).
Wskazówka 1
Rozwiązanie 1
Zadanie 7 (Pierwszy wspólny element list łączących się)
Dane są dwie listy proste (kończące się nilami) i takie że maja one element wspólny (funkcja Wspólny z poprzedniego zadania dałaby wynik true). Napisz funkcję odnajdującą pierwszy element wspólny tych list.
Wskazówka 1
Rozwiązanie 1
Ćwiczenie 1
Zadanie 8 (Listy z cyklem)
Napisz funkcje która sprawdzi czy dana l typu lista jest listą prostą czy też listą z cyklem.
Wskazówka 1
Rozwiązanie 1
Zadanie 8 (Długość cyklu w liście z cyklem)
Napisz funkcje która dla danej listy z cyklem obliczy długość cyklu.
Wskazówka 1
Rozwiązanie 1
Wskazówka 2
Rozwiązanie 2