Typy wskaźnikowe, dynamiczne struktury danych

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

Systemy czasu rzeczywistego
Katarzyna Szafrańska kl. II ti
PRAM.
STRUKTURY DANYCH.
Wskaźniki repetytorium Wskaźniki int Y = 1, X = 2; X = 5; int *p = &X; Y X p 4 4 p = &Y; *p = 4; 5.
Dynamiczne struktury danych Listy, Kolejki, Stosy
PASCAL (3) dr Anna Kwiatkowska.
PROGRAMOWANIE STRUKTURALNE
PROGRAMOWANIE STRUKTURALNE
ALGORYTMY I STRUKTURY DANYCH
Elementarne struktury danych Piotr Prokopowicz
OBJECT PASCAL Marzena Szałas.
Współprogramy III Ten wykład ma na celu pokazanie kolejnej ciekawej możliwości, którą oferują współprogramy. Wspólprogramy reprezentujące wyrażenia regularne.
ZŁOŻONOŚĆ OBLICZENIOWA
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 7: Procedury i funkcje © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 8: Wykorzystanie procedur i funkcji © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 6: Tablice, rekordy, zbiory.
Rekurencja Copyright, 2001 © Jerzy R. Nawrocki Wprowadzenie do informatyki Wykład.
Rekursja Copyright, 2004 © Jerzy R. Nawrocki Teoretyczne podstawy informatyki.
Kurs Pascala – spis treści
WYZWALACZE (TRIGGERY) Wyzwalacz jest specjalnym rodzajem procedury składowanej, która może być wykonana w odpowiedzi na jedną z trzech sytuacji: UPDATE.
Ogólne jednostki programowe 1
Dynamiczne struktury danych 1
Typy wskaźnikowe ogólne 1 Typy wskaźnikowe ogólne (general access types) umożliwiają pośredni dostęp (indirect access), czyli przez wskaźniki, do zadeklarowanych.
Wykład 2 struktura programu elementy języka typy zmienne
Analiza kosztu zamortyzowanego
22 listopada 2000Regula konkatenacji II1 Dziedziczenie (cd.) Reguła konkatenacji II przykład - heapsort Reguła konkatenacji III.
Typy wyrażenia, schematy blokowe, writeln, readln, if, pętle
Podprogramy.
Typy złożone, case, stałe. Typ zbiorowy type typ_zb = set of typ_podstawowy; Typem podstawowym może być tylko typ porządkowy. Typem podstawowym może być
PROGRAMOWANIE STRUKTURALNE
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
PROGRAMOWANIE STRUKTURALNE WYKŁAD 2
AWK Zastosowania Informatyki Wykład 1 Copyright, 2003 © Adam Czajka.
Podstawy programowania II
Podstawy programowania II
Programowanie strukturalne i obiektowe
Pliki tekstowe. Operacje na plikach. mgr inż. Agata Pacek.
Operacje na strukturach listowych
Andrzej Jędryczkowski Nie da się napisać większego programu bez podziału go na części zwane podprogramami. Podprogram to wyróżniona część programu.
© A. Jędryczkowski – 2006 r. © A. Jędryczkowski – 2006 r.
Pierwsze programy.
Wyrażenia w Turbo Pascalu.
Procedury i funkcje.
Definicja pliku tekstowego Operacje wykonywane na plikach tekstowych
Pliki Pojęcie i rodzaje plików Definicja typu plikowego Operacje wykonywane na plikach elementowych.
Pliki tekstowe – A. Jędryczkowski © 2007 Turbo Pascal umożliwia wykorzystanie w programach plików tekstowych. Pliki takie zawierają informację niezakodowaną
1 Wykład 8 Podprogramy. 2 Pojęcie i istota stosowania dzielenie programu na części (logicznie spójne) - nazwane - niezależne od pozostałych części - z.
Złożone typy danych Listy Tworzenie elastycznych baz danych
Jerzy F. Kotowski1 Informatyka I Wykład 14 DEKLARATORY.
Andrzej Repak Nr albumu
Inicjalizacja i sprzątanie
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Zbiory i rekordy mgr inż. Agata Pacek. Deklaracja typu zbiorowego (określa ilość elementów w zbiorze) type biegi=set of 0..6; Definiowanie zmiennej typu.
Visual Basic for Applications Poziom podstawowy Zajęcia 2
Wykład 10 typ zbiorowy rekurencja.
Dynamiczne struktury danych
Ogólna struktura programu w TP
Kurs języka C++ – wykład 9 ( )
Podstawowe struktury danych. Typy danych.
Podsumowanie wiedzy MPDI2 sem.3 INFORMATYKA. tworzenie nowego pliku i katalogu, nawigacja po katalogach, listowanie zawartości katalogu, zmiana nazw,
ALGORYTMY I STRUKTURY DANYCH
P ASCAL Definicje, deklaracje, podstawowe instrukcje 1.
Wykład 1 Informatyka II MPZI2 sem.letni. Tablice Tablice deklarujemy array [ lista typów indeksów ] of typ bazowy (składowych) np. var t1,t2:array [1..5,
Indeksy drzewiaste. ISAM ISAM - INDEXED SEQUENTIAL ACCESS METHOD Problem: –Dany jest plik uporządkowany – w jaki sposób zrealizować efektywnie zapytanie.
Typy wyliczeniowe, kolekcje
Listy.
nowe operatory & . (kropka) * operator rzutowy -> , (przecinek)
Zapis prezentacji:

Typy wskaźnikowe, dynamiczne struktury danych

Sterta przeznaczenie stosu (przypomnienie) sterta

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 }

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

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

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

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.

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.

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

Operator @ (TP) type tpr = ^real; var pr : tpr; x : double; t : array [0..5] of byte; begin pr = @x; pr^ := 2.718; { Nie wykonujemy dispose!!! } end. Operator @ 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.

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

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;

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;

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.

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;

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

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).

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

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 }

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.

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

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

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

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;

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;

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.

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;

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

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 }

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)

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

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

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

begin writeln('Początek: ',memavail); new(glowa); { to będzie element pusty} glowa^.dana:=-9999; { zakładamy, że nikt nie wstawi -10000 } 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.