Pobieranie prezentacji. Proszę czekać

Pobieranie prezentacji. Proszę czekać

Typy wskaźnikowe, dynamiczne struktury danych

Podobne prezentacje


Prezentacja na temat: "Typy wskaźnikowe, dynamiczne struktury danych"— Zapis prezentacji:

1 Typy wskaźnikowe, dynamiczne struktury danych

2 Sterta przeznaczenie stosu (przypomnienie) sterta

3 Typ wskaźnikowy type typ_wskaznikowy = ^typ_wskazywany; np.:
tpr = ^real; { zmienne typu pr będą} { wskaźnikami na zmienne real } var pr : tpr; { można było też od razu napisać pr: ^real }

4 Wskaźnik wskaźnik jak każda zmienna jest określony przez:
typ rozmiar – niezależny od typu zmiennej wskazywanej adres zbiór operacji – silnie ograniczony zmienna wskazywana to również zmienna własności wynikają z jej typu

5 Wskaźnik Rozmiar zmiennej wskaźnikowej: 4 bajty
kompilator 32-bitowy: 4B adres kompilator 16-bitowy: 2B segment + 2B offset kompilator 16-bitowy, „mały” model pamięci: 2B offset, segment domyślny Adres bezwzględny w pamięci fizycznej a przestrzeń adresowalna wskaźnikiem

6 Najważniejsze, oczywiste
Wskaźniki należy inicjalizować przed odwołaniem do zmiennych wskazywanych! alokacja nowej zmiennej (nie zapomnij o dealokacji) przypisanie adresu istniejącej zmiennej

7 Inicjalizacja wskaźnika
Procedury new i dispose var pr : ^real; begin new(pr); { rezerwacja obszaru pamięci (6 bajtów - tyle ma real) } { Teraz można używać zarezerwowanego obszaru } pr^ := 2.718; { tak się odwołujemy do zarezerwowanego obszaru } pr^ := 2*pr^; { identycznie jak wyżej, pr^ jest typu real } writeln(pr^); { identycznie jak wyżej, pr^ jest typu real } { Po zakończeniu używania zarezerwowanego obszaru pamięci} { należy go koniecznie zwolnić!!! } dispose(pr); { Od tej chwili nie należy używać pr^ } end.

8 Zwolnienie wskaźnika Nie należy zwalniać niezarezerwowanego obszaru pamięci ani zwalniać ponownie tego samego (już zwolnionego) obszaru pamięci! Jeśli programista nie zwolni zarezerwowanego przez siebie obszaru pamięci, to nie będzie on dostępny dla następnych wywołań procedury new. Jednak po zakończeniu wykonywania programu wszystkie zarezerwowane obszary zostaną automatycznie zwolnione. Podobny efekt, ale przed zakończeniem programu, można uzyskać wykorzystując parę procedur mark i release.

9 nil wyróżnina, specjalna wartość zmiennej wskaźnikowej każdego typu wskaźnikowego nil w innych językach

10 Operator @ (TP) type tpr = ^real; var pr : tpr; x : double;
t : array [0..5] of byte; begin pr pr^ := 2.718; { Nie wykonujemy dispose!!! } end. zwraca typ wskaźnikowy nie związany z konkretnym typem bazowym (pointer). Dlatego możliwe jest „mieszanie typów” i odwoływanie się do tego samego obszaru pamięci traktując go jak zmienne różnych typów.

11 Wskaźniki do funkcji i procedur
Po co nam wskaźniki do funkcji i procedur?

12 To się przydaje: wskaźniki do struktur zawierających wskaźniki
czy na każdą zmienną alokowaną dynamicznie musi przypadać jeden wskaźnik? type tr2 = ^telem; telem = record { taki typ będzie czytelniejszy } { po narysowaniu } dana: real; { ew. inne pola } nast: tr2 end;

13 Lista dynamiczna type tr2 = ^telem; telem = record dana: real;
{ ew. inne pola } nast: tr2 end; var glowa, p1 : tr2; procedure wypisz(el: tr2); begin while el<>nil do writeln(el^.dana); el:=el^.nast end end;

14 begin new(p1); glowa := p1; { utwórz pierwszy element} p1^.dana := 10.0; p1^.nast := nil; {kolejny element} new(p1); { nowa zmienna dynamiczna! } p1^.nast := glowa; { wstawimy na początek listy } glowa := p1; { czyli to jest nowy początek listy } p1^.dana := 8.0; wypisz(glowa); { usun(glowa); } {wypada posprzątać } end.

15 Usuwanie listy procedure usun(el: tr2); var p: tr2; begin
while el<>nil do p:=el; el:=el^.nast; dispose(p); { UWAGA: po tym nie można byłoby } { wykonać el:=el^.nast ! } end end;

16 Struktury dynamiczne Lista jednokierunkowa Lista dwukierunkowa
Listy cykliczne Drzewo binarne Inne drzewa Lista a tablica – kiedy wybrać listę?

17 Wskaźniki (16-bit TurboPascal)
Funkcja Addr(X):pointer. X może być zmienną lub identyfikatorem programu. Funkcja Ofs(X):word zwraca offset zmiennej (podprogramu) X. Funkcja Seg(X):word zwraca segment zmiennej (podprogramu) X. Funkcja Ptr(Seg, Ofs: Word): Pointer tworzy wskaźnik na podstawie podanych wartości segmentu i offsetu. Adresy wirtualne (kod 16-bit, maszyna 32-bit).

18 Wskaźniki (16-bit TurboPascal)
Przypisania dozwolone pomiędzy różnymi typami wskaźników (nie sprawdzane)! funkcja memavail funkcja maxavail typ pointer

19 Wskaźniki (16-bit TurboPascal)
Tablice predefiniowane mem* i port* (mem, memw, meml ) mem[$1234:$5678]:=85 Słowo kluczowe absolute var a: real; { nowa zmienna } b: integer absolute $b000:0000; { określenie konkretnego } {miejsca w pamięci } c: integer absolute a; { zmienna c w tym samym miejscu} { pamięci co zmienna a }

20 type tekran = array[0..24,0..79] of record
znak, atrybut: byte end; tel = record k: integer; { klucz } wyst: integer; { liczba wystąpień } lewy,prawy: pel var ekran: tekran absolute $b800:0 { mode co80; dla mode mono: $b000:0 } e2: tekran; { np. do zapamiętywania zawartości ekranu } begin ekran[0,10].znak:=65; { litera A na 11 pozycji górnego wiersza ekranu } e2:=ekran; { zapamiętanie zawartości całego ekranu } {.....} ekran:=e2; { odtworzenie zawartości całego ekranu } end.

21 Wskaźniki UWAGA: struktura s zmniejszy dostępny obszar sterty o nie mniej niż sizeof (s) Fragmentacja pamięci – to jest problem: użyj maxavail

22 Przykłady Wstawianie elementu na koniec listy Lista dwukierunkowa.
Wyszukiwanie elementu w liście. Lista cykliczna. Testowanie cykliczności listy. Drzewo binarne. Stos, kolejka. Uporządkowane drzewo binarne

23 Listy dynamiczne Uwaga na przypadki szczególne:
lista jest pusta lista ma tylko jeden element jesteśmy na początku/końcu listy Uwaga na przypadek typowy: nie początek i nie koniec nie pustej listy

24 Przykład Uporządkowane drzewo binarne type pel = ^tel; tel = record
k: integer; { klucz } wyst: integer; { liczba wystąpień } lewy,prawy: pel end; var korzen: pel;

25 procedure wstaw(var p:pel; dana: integer);
begin if p=nil then new(p); with p^ do { problematyczne to with! } k:=dana; wyst:=1; lewy:=nil; prawy:=nil end else if dana=p^.k then inc(p^.wyst) if dana<p^.k then wstaw(p^.lewy,dana) wstaw(p^.prawy,dana) end;

26 procedure wypisz(p:pel);
begin if p<>nil then wypisz(p^.lewy); writeln(p^.k:5,' (',p^.wyst,')'); wypisz(p^.prawy); end end; wstaw(korzen,3); wstaw(korzen,1); wstaw(korzen,4); { } wstaw(korzen,5); wypisz(korzen); end.

27 Przykład Uporządkowane drzewo binarne – zalety tej struktury dynamicznej type pel = ^tel; tel = record k: integer; { klucz } wyst: integer; { liczba wystąpień } lewy,prawy: pel end; var korzen: pel;

28 Przykład Sortowanie listy przez proste wstawianie
type tw = ^tel; tel = record dana: real; nast: tw end; const glowa: tw = nil; Mniej przypadków szczególnych: pomocniczy element na początku listy

29 type tw = ^tel; tel = record dana: real; nast: tw end; const glowa: tw = nil; procedure wstaw(co: tw); { wyszukuje miejsce i wstawia } procedure wypisz(p: tw); { wypisuje całą listę } procedure usun(var p: tw); { usuwa całą listę } function nowy(x:real):tw; { alokuje element i zwraca jego adres }

30 procedure wstaw(co: tw); { wyszukuje miejsce i wstawia }
var p,p1:tw; begin { Zakładamy, że mamy na początku wartownika!!! } p1:=glowa; p:=glowa; while (p<>nil) and (p^.dana<co^.dana) do p1:=p; p:=p^.nast; end; { tutaj p=nil albo p^.dana>=co^.dana, czyli musimy wstawić PRZED p^, czyli ZA p1^ } wstaw_za(co,p1)

31 Jak wstawić za danym elementem?
procedure wstaw_za(co, za_czym: tw); { wstawia co^ za za_czym^ } var p:tw; begin if za_czym = nil then writeln('Za nilem nie wstawiam'); halt end; co^.nast:=za_czym^.nast; za_czym^.nast:=co

32 procedure wypisz(p: tw);
begin writeln(' '); while p<>nil do writeln(p^.dana:10:5); p:=p^.nast end end; procedure usun(var p: tw); var p1: tw; p1:=p^.nast; dispose(p); p:=p1

33 function nowy(x:real):tw;
var p: tw; begin if maxavail<sizeof(p^) then writeln('Zabrakło pamięci'); halt end; new(p); p^.dana:=x; p^.nast:=nil; nowy := p

34 begin writeln('Początek: ',memavail); new(glowa); { to będzie element pusty} glowa^.dana:=-9999; { zakładamy, że nikt nie wstawi } glowa^.nast:=nil; wstaw(nowy(2)); { wstawianie w odpowiednie miejsce listy } wstaw(nowy(-333)); wstaw(nowy(4)); wypisz(glowa); usun(glowa); writeln('Koniec: ',memavail); end.


Pobierz ppt "Typy wskaźnikowe, dynamiczne struktury danych"

Podobne prezentacje


Reklamy Google