Podstawy Programowania semestr drugi. Wykład trzeci

Podobne dokumenty
Badanie funktorów logicznych TTL - ćwiczenie 1

Rozdział 4 Instrukcje sekwencyjne

Podstawy Programowania semestr drugi. Wykład czternasty

WYKORZYSTANIE STATISTICA DATA MINER DO PROGNOZOWANIA W KRAJOWYM DEPOZYCIE PAPIERÓW WARTOŚCIOWYCH

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Ćwiczenie 3 stos Laboratorium Metod i Języków Programowania

Układy sekwencyjne asynchroniczne Zadania projektowe

Ę Ż ż Ł ź ż ż ż ż

ć Ę ć Ę ź Ę

ź Ć Ż

Ż ź Ł

ć ć ć

Ą Ę Ł Ą Ż

ź Ź Ź ć ć ć ź ć ć ć ć ć Ź

Ą ŚĆ Ś Ś Ę ć

Ł

ś ś ś ź ć ś ś

Ę

ś ś ś ś ś ś ś ś ś ś ć ś Ż Ż ć ś ś Ż ć

ń

ś ść ść ś ść ść ś ś ś ś ść ś ś ś ść ść

Podstawy programowania. Wykład PASCAL. Zmienne wskaźnikowe i dynamiczne. dr Artur Bartoszewski - Podstawy prograowania, sem.

Lista 5 Typy dynamiczne kolejka

DYNAMICZNE MODELE EKONOMETRYCZNE

LABORATORIUM PODSTAWY ELEKTRONIKI Badanie Bramki X-OR

Ś Ę Ą Ł Ś Ł Ł Ł Ł Ł Ś Ś Ł Ł Ł Ą Ł Ł Ł Ł Ł Ą Ą Ł

ZASADY PROGRAMOWANIA KOMPUTERÓW

Ą Ł ć Ę ć Ę ć

ć ć Ł ć Ź ć Ł ź ć Ś ć ć Ż Ł Ż ć ż ć

. Podstawy Programowania 2. Jednokierunkowa lista liniowa. Arkadiusz Chrobot. 28 marca 2017

ć Ą Ą Ł Ą

Ę Ż Ż Ż ś ż Ż

ć

ć ż ż ż ź

ż ć

ź Ą Ę Ę ć Ł ć ć ć ć ć ć ć

Ą Ą Ł

ć Ę ć ć ć ć ą

Ą Ą

Ż Ć Ź Ź Ż Ą Ą ć Ź Ź Ć Ę

Ę Ą Ż ć Ę Ż Ł ź

ż

Ś

Ł ż

ć Ę Ę ć Ę ć Ę Ę Ę

Ę Ą Ł Ę Ł ć

ć ć ć ć ć Ł

Ż ź Ś Ż

ć ż ż ć Ą ż ż Ł ć Ż ż Ż Ż Ż Ż

Ą Ó Ś ź Ś

Ć ć ć Ś ć

ć Ś Ś Ść


C e l e m c z ę ś c i d y s k u s y j n e j j e s t u ś w i a d o m i e n i e s o b i e, w o p a r c i u o r o z w a ż a n i a P i s m a Ś w.

ć ć Ą ć Ęć Ó Ą ź ć ć ć ć ź ź Ą ć Ę ć ź ć ć ć ź ć ź ć ć ć Ś Ź ź

ż ż ź ć ć ć ć ż

Ś Ę ŚĆ Ę ź ź ź Ś Ś Ś ć ź Ś ź Ę Ś Ą ź ź ź Ś Ś Ę ź ź

ć Ę ż Ł ź ż ź Ś Ś ź ć Ć ż Ś ż Ś

Ł ż Ó Ó ć Ó Ć

ć

ś ś ś Ł ś

Ż Ę Ż Ł Ą ź ć ć ć

ć ć ż ć ź ż ż ź ź ŚĆ Ź ź ć Ź ź ź ź ź Ś Ą Ć Ć ć Ź ź

ź Ś Ó Ó Ż

ż ż Ż Ł

Ę Ę ć ć Ę Ą Ę Ą Ę Ę Ę Ę Ę Ę ź Ę Ż Ę Ę Ę Ę ć Ę Ę ć Ę ć

Ę

Ł Ó Ó Ó Ł Ó Ó Ł Ł Ó Ą Ć Ó Ą ć Ó ć ć

ż ż ż ż Ź ż Ą ż ż ż Ś

Ź ć Ż ć ć Ó

ć ć ć Ó ć Ó ć Ę ć Ł ć Ś ć Ę ć Ą ć ć ć ć ć ć ć

ć ź Ż Ń

Ł ź Ń

Ó Ś Ś ć

Ó Ł Ę ź ź ź ć Ó ć

Ń ć Ł Ł Ł ź

Ą Ź ć ć Ó Ó Ć Ć Ś

ż ń Ł ń ń ż ż ż ż ż

ń ń ń ń ń Ż ć Ż Ł Ż Ł Ś ć ń Ś Ę Ż ć ń Ż Ż Ż Ą Ż Ż Ł Ż Ś

Ś

ć ż Ą ż ż ż ż ż ż ż Ę Ę

ć ć ź ć ć ć Ść ć ź ź ź ć ź Ą ź

Ś Ż Ó Ś ż Ó ć ź ż ż Ą

Ś Ę ź Ń

ż ń ń ń ż ń ń Ę ń ć ń ż ń Ę

Ś ć ź ź Ę ź ź Ę Ę Ą Ś Ę Ś Ę ź Ę Ś Ś Ę Ś Ś Ł Ś


ż

Ń ź ź Ą Ń Ą ć ć ć ć ć Ń Ą

Ż Ź Ż ż Ś Ś Ź Ż Ż Ż Ż Ż ć ć Ż

Ż ń ć ć ń Ż ć Ż Ł ń Ż ń ń ń ń

ż ć ć ć ć ć ż Ę ż Ę ż Ł Ą ż ń Ą Ł

ć Ę ć ć ć Ł ć ń ć ć ć ń ć

Podstawy Programowania 2 Jednokierunkowa lista liniowa. Plan. Jednokierunkowa lista liniowa. Jednokierunkowa lista liniowa. Notatki. Notatki.

Ł Ś Ł Ś ć ć ć ź Ę ć ć ź ć ć ć ć ć Ę ć ć

Ę

Ę ć ć Ę Ą Ę

ć ż ż Ś ż


ś ś ś Ź Ę Ć ś ś ś ć ś ś ś ś ś ś ś ś ś ś Ą

Transkrypt:

1. Kolejki Wykład rzeci Kolejka jes, podobnie jak sos, absrakcyjn ą srukur ą danyc opar ą na liście liniowej. Elemeny kolejki e ż s ą połączone w lis ę, ale inaczej ni ż w sosie przebiegają operacje dodawania i usuwania elemenów z ej lisy. Isnieje kilka odmian kolejek. W najprosszej dodawanie i usuwanie elemenów jes zorganizowane według zasady FIFO (ang. Firs In Firs Ou) pierwszy nadszed ł, pierwszy wycodzi. Elemeny dodawane s ą do kolejki na jej końcu, naomias usuwane s ą z jej począku. Mówiąc lub pisząc kolejka mamy najczęściej na myśli opisan ą wyżej srukur ę. Oprócz niej isniej ą równie ż kolejki dwusronne, w kóryc elemeny możemy dodawać i usuwa ć po obu sronac kolejki. Wśród yc kolejek możemy wyróżni ć kolejki o ograniczonym wejściu, w kóryc operacja dodawania doyczy ylko jednego końca kolejki, a operacja usuwania obu, oraz kolejki o ograniczonym wyjściu, w kóryc operacja usuwania doyczy ylko jednego końca kolejki, a operacja dodawania obu końców. Dalsze rozważania będ ą doyczyły ylko kolejki FIFO. 2. Implemenacja kolejki w oparciu o lis ę liniową Typ pojedynczego elemenu kolejki (yp bazowy kolejki) będzie określony ak samo jak yp bazowy sosu 1 : ype wskaznik=^elemen; elemen=record :ineger; nex:wskaznik; Aby wygodnie korzysa ć z kolejki wprowadza si ę dwie zmienne wskaźnikowe ead (po polsku głowa) i ali (po polsku ogon), kóre wskazuj ą odpowiednio na pierwszy i na osani elemen kolejki. Mając określony yp elemenu i obie zmienne wskaźnikowe należy jeszcze określi ć operacje, kóre będ ą na ej kolejce wykonywane. Podobnie jak w przypadku sosu yc operacji może by ć kilka, jednak uaj zosan ą omówione dwie najważniejsze wsawienia elemenu do kolejki (ang. enqueue) i usunięcia elemenu z kolejki (ang. dequeue) oraz dodakowo operacja wyświelenia warości pola dane wszyskic elemenów należącyc do kolejki. Procedura enqueue posiada rzy paramery. Przez dwa pierwsze przekazywane s ą wskaźniki odpowiednio na pierwszy i osani elemen kolejki, naomias poprzez rzeci przekazywana jes waro ść, kór ą ccemy umieści ć w elemencie. Procedura a posiada równie ż zmienn ą lokaln ą, kóra będzie wskazywała na elemen kolejki, kóry zosanie w niej uworzony. Proces worzenia nowego elemenu dokonywany jes w wierszac 5 7. Najpierw przydzielona jes, za pomoc ą procedury new, pami ęć na en elemen. Poniewa ż nowe elemeny dodawane s ą na końcu kolejki, o ic pole wskazujące na kolejny elemen powinno mie ć waro ść 2. Waro ść a nadawana jes emu polu w wierszu 7. Jeżeli procedura dopiero worzy pierwszy elemen kolejki, o nie może go doda ć do jej końca, poniewa ż kolejka nie isnieje. Aby swierdzi ć, czy pierwszy elemen kolejki isnieje wysarczy sprawdzi ć, czy wskaźnik na pierwszy elemen nie jes równy, jeśli ak, o kolejka isnieje i można do niej doda ć kolejny elemen (wiersze 9 12), jeśli nie należy uworzony elemen porakowa ć ak, jakby mia ł by ć o pierwszy elemen ej kolejki (wiersze 14 17). Można o zilusrowa ć nasępującym rysunkiem: 1 procedure enqueue(,:wskaznik; a:ineger); 2 3 :wskaznik; 4 1. Tworzony jes pierwszy elemen kolejki 1. Przed wykonaniem wiersza 10 2. Po wykonaniu wiersza 10 5 new(); 6 ^.:=a; 7 ^.nex:=nil; 3. Po wykonaniu wiersza 11. 8 if =nil en 9 2. Dodawany jes kolejny elemen do kolejki 1. Przed wykonaniem wiersza 15 10 :=; 11 :=; 12 end 2. Po wykonaniu wiersza 15 13 else 14 nex 15 ^.nex:=; 16 :=^.nex; 17 3. Po wykonaniu wiesza 16 nex 18 1 Zmiana nazwy pola przecowującego wskaźnik na nasępny elemen nie ma u większego znaczenia. 2 Ta waro ść oznacza, że za ym elemenem nie ma ju ż innyc elemenów. 1

Wyjaśnienia wymaga wiersz szesnasy procedury: poniewa ż we wcześniejszym wierszu zapisaliśmy adres nowego elemenu w polu nex osaniego elemenu kolejki, o elemen powinien zosa ć eraz elemenem osanim kolejki. Aby ak było musi na niego wskazywa ć wskaźniki. Wysarczy mu więc nada ć waro ść ak ą, jaka jes w polu nex bieżącego elemenu. Możemy równie ż en wiersz zasąpi ć insrukcj ą :=; Procedura prinqueue drukuje zawaro ść kolejki na ekran moniora: 1 procedure prinqueue(:wskaznik); 2 3 wile <> nil do 4 5 wrie(^.,#32); Procedura a pobiera przez paramer wskaźnik na pierwszy elemen kolejki. Jes on przekazywany przez waro ść, aby można było posługiwa ć si ę paramerem wewnąrz procedury, nie zmieniając przy ym warości zmiennej jaka będzie za niego podsawiona. W wierszu 5 wypisywana jes zawaro ść pola bieżącego elemenu, a w wierszu 6 wskaźnikowi nadawana jes waro ść, jaka jes przecowywana w polu nex bieżącego elemenu, dzięki czemu będzie wskazywa ł na kolejny elemen w kolejce. Te dwie insrukcje zaware s ą w pęli wile, kóra kończy si ę w momencie uzyskania przez zmienn ą wskaźnikow ą warości. 6 :=^.nex; 7 8 wrieln; 9 Procedura dequeue usuwa elemen z kolejki: 1 procedure dequeue( :wskaznik; a:ineger); 2 3 emp:wskaznik; 4 5 emp:=^.nex; 6 a:=^.; 7 dispose(); Procedura a ma dwa paramery: pierwszy jes wskaźnikiem na pierwszy elemen kolejki, a przez drugi procedura zwraca waro ść zapisan ą w ym elemencie ( ę procedur ę można równie ż zapisa ć jako funkcj ę, lub procedur ę, kóra nic nie zwraca). W procedurze jes akże zadeklarowana lokalna zmienna wskaźnikowa, kóra będzie wykorzysywana do zapamięywania adresu nasępnego elemenu w kolejce. Procedura dequeue usuwa pierwszy elemen znajdujący si ę w kolejce. W wierszu 5, w zmiennej emp zapamięywany jes wskaźnik na elemen znajdujący si ę u ż za pierwszym elemenem kolejki, nasępnie w wierszu 6 paramerowi a nadawana jes waro ść, kóra jes zapamięana w pierwszym elemencie, po czym w wierszu 7 zwalniana jes pami ęć przeznaczona na en elemen. Poniewa ż powinien wskazywa ć na począkowy elemen kolejki, a w ej cwili jes nim elemen znajdujący si ę za zwolnionym wcześniej elemenem, więc jego adres, zapamięany w zmiennej emp jes przepisywany do zmiennej. 8 :=emp; 9 3. Przykład Poniżej przedsawiono program, kóry pobiera od użykownika pewn ą liczb ę warości całkowiyc (ypu ineger ) i zapisuje je w kolejce, a nasępnie wypisuje je na ekran oraz likwiduje kolejk ę, wypisując ponownie zapisane w niej liczby: program queue; uses cr; ype wskaznik=^elemen; elemen=record :ineger; nex:wskaznik; ead,ail:wskaznik; ne,nu:ineger; procedure enqueue(,:wskaznik; a:ineger); :wskaznik; 2

new(); ^.:=a; ^.nex:=nil; if =nil en :=; :=; end else ^.nex:=; :=^.nex; procedure prinqueue(:wskaznik); wile <> nil do wrie(^.,#32); :=^.nex; wrieln; procedure dequeue( :wskaznik; a:ineger); emp:wskaznik; emp:=^.nex; a:=^.; dispose(); :=emp; wrieln('dosępna pami ęć: ',MemAvail); wrieln('ile elemenów umieści ć w kolejce?'); readln(ne); wile ne>0 do wrieln('podaj waro ść elemenu: '); readln(nu); 3

enqueue(ead,ail,nu); dec(ne); wrieln('dosępna pami ęć: ',MemAvail); wrieln('w kolejce umieszczono nasępujące elemeny: '); prinqueue(ead); wrieln('a eraz niszczymy kolejk ę:'); wile ead<>nil do dequeue(ead,nu); wrieln(nu); wrieln('dosępna pami ęć: ',MemAvail); end. 4. Implemenacja kolejki za pomoc ą ablicy W ym podpunkcie zosanie przedsawiony program, kóry buduje kolejk ę w oparciu o ablic ę. Pojemno ść akiej kolejki jes ograniczona rozmiarem ablicy, niemniej jednak waro zapozna ć si ę z jej działaniem, gdy ż rozwiązany jes u problem kopiowania elemenów ablicy, jeśli usuwany jes elemen z kolejki. Przedsawiona implemenacja nazywa si ę cykliczn ą implemenacj ą ablicow ą kolejki. Na ej samej zasadzie działa bufor klawiaury w BIOSie. W ej implemenacji jeden elemen ablicy jes zawsze niewykorzysany. Zaprezenowane w programie procedury zosały zaczerpnięe z książ ki Alfreda V. Ao, Jona E. Hopcrofa i Jeffrey'a D. Ullmana Algorymy i srukury danyc : program abqueue; uses cr; cons maxleng = 20; Funkcja addone zwiększa przekazan ą jej waro ść o jeden modulo liczba elemenów w ablicy. Wskaźniki ead i ail zosały zasąpione zmiennymi indeksowymi firs i las. Procedura makenil usuwa wszyskie elemeny z kolejki, czyli j ą likwiduje. Funkcja empy zwraca waro ść rue, jeśli w kolejce nie ma żadnyc elemenów, w przeciwnym przypadku zwraca waro ść false. Funkcja firsone zwraca warość pierwszego elemenu z kolejki. ype queue = record elemens: array[1..maxleng] of ineger; firs, las:bye; qu:queue; ne:bye; nu:ineger; funcion addone(i: bye):bye; addone := i mod maxleng + 1; 4

procedure makenil( q:queue); q.firs:=1; q.las:=maxleng; funcion empy(cons q:queue):boolean; if addone(q.las) = q.firs en empy:=rue else empy:=false; funcion firsone(cons q:queue):ineger; firsone:=-maxin; if empy(q) en exi else firsone:=q.elemens[q.firs]; procedure enqueue( q:queue; a:ineger); if addone(addone(q.las)) = q.firs en exi else q.las:=addone(q.las); q.elemens[q.las]:=a; procedure dequeue( q:queue); if empy(q) en exi else q.firs:=addone(q.firs); makenil(qu); wrieln('ile elemenów umieści ć w kolejce: '); readln(ne); wile ne>0 do readln(nu); enqueue(qu,nu); dec(ne); 5

wrieln('elemeny umieszczone w kolejce: '); wile no empy(qu) do nu:=firsone(qu); dequeue(qu); wrie(nu,#32); end. 5. Tesowanie niekóryc operacji srukury dynamicznej Tworzenie oprogramowania, kóre korzysa ze zmiennyc i srukur dynamicznyc jes dosy ć złożonym zajęciem, podczas kórego można popełni ć wiele błędów. Znajdywanie i usuwanie akic userek jes bardzo uciążliwe ze względu na carakerysyk ę zmiennyc dynamicznyc. Isnieje jednak sposób, aby przeesować operacje na srukurac dynamicznyc, kóre nie przydzielaj ą, ani nie zwalniaj ą pamięci, przy pomocy zmiennyc saycznyc. Kolejk ę FIFO można zbudować z elemenów będącyc zmiennymi lokalnymi lub globalnymi, ale wskazującymi na siebie. Odpowiednie warości polom wskaźnikowym poszczególnyc elemenów można nada ć za pomoc ą operaora @ lub funkcji addr. Tak uworzone kolejki nie maj ą zazwyczaj zby wielu elemenów, ale dzięki nim możemy przeesowa ć, czy operacja działa poprawnie, zanim zasosujemy j ą do kolejki worzonej dynamicznie i zaryzykujemy powsanie wycieków pamięci. Rozwiązanie o można zasosowa ć nie ylko do kolejek FIFO, ale akże do innyc absrakcyjnyc srukur danyc, kóre zosan ą omówione na nasępnyc wykładac. Poniżej znajduje si ę program, kóry pozwala sprawdzi ć działanie procedury prinqueue na kolejce saycznej składającej si ę z rzec elemenów (zmienne globalne a, b i c ). program esowanie; uses cr; ype wskaznik = ^elemen; elemen = record :ineger; nex:wskaznik; ead:wskaznik; a,b,c:elemen; procedure prinqueue(:wskaznik); wile <>nil do wrie(^.,#32); :=^.nex; wrieln; 6

a.:=1; a.nex:=@b; b.:=2; b.nex:=@c; c.:=3; ead:=@a; prinqueue(ead); end. Do uworzenia kolejki saycznej zosa ł wykorzysany en sam yp elemenu, kóry służy do worzenia kolejki dynamicznej, jednakże zamias zmiennyc dynamicznyc ypu wskaznik zosały uworzone rzy zmienne rekordowe ( a, b i c ) ypu elemen, będące zmiennymi globalnymi. Poniewa ż procedura prinqueue przyjmuje przez paramer ylko wskaźnik na pierwszy elemen kolejki, o zamias dwóc wskaźników do obsługi kolejki zosa ł zadeklarowany ylko jeden ( ead ). W bloku głównym programu, inicjalizowane s ą poszczególne elemeny kolejki, j. w ic polac zapisywane s ą liczby (odpowiednio: 1, 2 i 3) oraz w polac wskaźnikowyc zapisywane s ą adresy elemenów na kóre będ ą one wskazywa ć. Elemen a będzie wskazywa ł na b, a en będzie wskazywa ł na c. Polu nex elemenu c nie rzeba nadawa ć warości, gdy ż jes on zmienn ą globaln ą i w związku z ym o pole ju ż ma ak ą waro ść. Do wskaźnika ead zapisywany jes adres pierwszego elemenu kolejki ( a ). Ten wskaźnik przekazywany jes wywoływanej procedurze prinqueue. Jeżeli jes ona napisana poprawnie, o na ekranie ujrzymy liczby 1, 2 i 3 rozdzielone znakami spacji. Gdyby było inaczej, o nie zobaczymy żadnej liczby, lub będzie kórej ś brakowało. 6. Uwagi końcowe Niekórzy programiści deklaruj ą wskaźniki ead i ali jako pola rekordu, co może uławia ć zarządzanie nimi. Dosy ć częso, aby uprości ć działanie i kod podprogramów obsługującyc kolejki, na począku programu worzy si ę pojedynczy elemen, kóry nie jes prawdziwym elemenem kolejki, ale arap ą. Dzięki niemu nie rzeba wprowadza ć do podprogramów kodu obsługującego przypadki, kiedy kolejka nie isnieje. Ten elemen nazywa si ę warownikiem, a kolejk ę kolejką z warownikiem. To rozwiązanie można zasosowa ć równie ż w przypadku sosu. W kodzie programu worzącego dynamicznie elemeny kolejki nie jes sprawdzana poprawno ść przydziału pamięci 3. W przypadku środowiska Turbo Pascal należałoby najpierw nada ć zmiennej lokalnej z procedury enqueue waro ść, a nasępnie, po wykonaniu procedury new sprawdzi ć, czy ak ą ona nie pozosała. Procedura new ze środowiska Free Pascal sama nadaje waro ść przekazanemu jej przez paramer wskaźnikowi, zaem można pomin ąć krok inicjalizacji zmiennej lokalnej, a jedynie sprawdzi ć, czy po wywołaniu procedury new nie ma ona warości. 3 Ta uwaga doyczy akże programów zaprezenowanyc na poprzednim wykładzie, kóry rakowa ł o sosie. 7