Metody i jezyki programowania -- zbiór zadan lista 5

Transkrypt

Metody i jezyki programowania -- zbiór zadan lista 5
Uniwersytet Zielonogórski
Instytut Sterowania i Systemów Informatycznych
Metody i języki programowania
Lista 5 – Typy dynamiczne – kolejka
1
Wprowadzenie
Kolejka jest jedną z podstawowych struktur umożliwiających przechowywanie i przetwarzanie
danych w pewien przyjęty sposób. Kolejki są powszechnie wykorzystywane we współczesnych
systemach komputerowych. Przykładem sprzętowym może być obsługa instrukcji programu
przez procesor. W warstwie oprogramowania kolejki są powszechnie stosowane w systemach
realizujących obsługę zamówień. Najprostszym przykładem kolejki jest oczywiście wykorzystanie takiej struktury przez klientów sklepów. „Samoczynnie” ustawiają się oni w kolejce chcąc
zapewnić każdemu „sprawiedliwie” przydzielony czas oczekiwania na obsługę.
2
Zasady tworzenia i obsługi kolejki
Budowa kolejki opiera się na prostych założeniach.
1. Elementy do kolejki dodawane są tylko na jej końcu. Element dodany do kolejki staje się
automatycznie jej ostatnim elementem.
2. Jedynie element znajdujący się na początku kolejki może być obsłużony. Oznacza to jego
automatyczne usunięcie z kolejki.
3. Elementy są uszeregowane w taki sposób iż kolejność obsługi wynika z miejsca położenia.
Kolejka jest więc strukturą FIFO (First Input First Output).
Rysunek 1: Przykładowa kolejka. T oznacza czas wstawiewienia elementu do kolejki.
1
3
Tworzenie kolejki na podstawie struktur dynamicznych
Kolejka składa się z uporządkowanych elementów. Podobnie jak w stosach elementy te zawierają
wskaźnik na obiekty strukturalne typu takiego samego jak ten, do którego należą. Definicja typu
rekordowego wykorzystywanego w kolejce może być więc identyczna z definicją typu elementu
wchodzącego w skład stosu. W przypadku przechowywania w kolejce liczb typu integer ma ona
postać:
type
TWskaznikNaStrukture = ˆ TTypStruktury ;
TTypStruktury = r e c o r d
DANE : i n t e g e r ;
Nastepny : TWskaznikNaStrukture ;
end ;
3.1
Tworzenie wskaźników początku i końca kolejki
Podobnie jak w przypadku stosu, do poprawnej obsługi kolejki wystarczyłby by tylko jeden
wskaźnik. W przypadku kolejki pokazanej na rys. 1 byłby to wskaźnik na początek kolejki. W oczywisty sposób wskaźnik ten jest wystarczający w przypadku usunięcia pierwszego
elementu z kolejki. Jeżeli chcielibyśmy dodać element do kolejki należałoby „przejść” przez
wszystkie elementy kolejki (od pierwszego do ostatniego) i dopiero po wyznaczeniu jej końca
rozpocząć dodawanie nowego elementu. W celu przyspieszenia obsługi kolejki wykorzystuje się
drugi wskaźnik, przechowywujący adres jej końca.
Pierwszym krokiem, który należy wykonać przed utworzeniem nowej kolejki, jest deklaracja
zmiennych przechowujących wskaźniki na początek i koniec kolejki.
var Poczatek , Koniec : TWskaznikNaStrukture ;
Rysunek 2: Utworzenie wskaźników do początku i końca kolejki
W celu uniknięcia błędów mogących się pojawić po utworzeniu wskaźników do nieistniejącej
jeszcze kolejki, należy ustawić ich wartości na NIL. Procedury (funkcje) wykonujące operacje
na kolejce powinny sprawdzać czy wskaźniki mają wartości różne niż NIL w celu określenia czy
kolejka istnieje. Należy także pamiętać o przypisaniu wskaźnikom wartości NIL po usunięciu
ostatniego elementu kolejki (rys. 3).
Poczatek := n i l ;
Koniec := n i l ;
3.2
Tworzenie pierwszego elementu
Po zadeklarowaniu wskaźników do początku i końca kolejki można przystąpić do utwrzenia
pierwszego elementu kolejki. W celu uproszczenia procedury dodawania nowego elementu do
2
Rysunek 3: Poprawne ustawienie wartości nowo-utworzonego wskaźnika do początku i końca
kolejki
kolejki wykorzystamy wskaźnik tymczasowy na element kolejki (umożliwi to zastosowanie tej
samej procedury dodawania elementu również w przypadku gdy kolejka zawiera elementy).
Deklaracja wskaźnika tymczasowego:
var Tmp: TWskaznikNaStrukture ;
Utworzenie elementu:
new (Tmp) ;
Rysunek 4: Krok 1 - dodawanie pierwszego elementu do kolejki
Po utworzeniu nowego elemntu można przypisać mu dowolne (wymagane przez działanie
programu) dane.
Tmpˆ .DANE : = 1 ;
Rysunek 5: Krok 2 - dodawanie pierwszego elementu do kolejki
Ponieważ do kolejki elementy zawsze dodajemy na jej koniec to ostatni element (nowo
utworzony) nie może wskazywać na żaden kolejny element. Dlatego też do wskaźnika należy
przypisać NIL.
Tmpˆ . Nastepny := NIL ;
3
Rysunek 6: Krok 3 - dodawanie pierwszego elementu do kolejki
Utworzony element jest pierwszym dodanym do kolejki więc należy go przypisać do wskaźnika Pierwszy.
Poczatek := Tmp;
Rysunek 7: Krok 4 - dodawanie pierwszego elementu do kolejki
Każdy nowo dodany element do kolejki jest ostatnim jej elementem, więc należy przypisać
go do wskaźnika na koniec kolejki.
Koniec := Tmp;
Rysunek 8: Krok 5 - dodawanie pierwszego elementu do kolejki
W efekcie powyższych działań powstała kolejka zawierająca jeden element.
3.3
Następne elementy
Jeżeli chcemy dodać drugi element do kolejki, należy go utworzyć wykorzystując wskaźnik
tymczasowy (tak jak w przypadku dodawania pierwszego elementu do kolejki):
new (Tmp) ;
4
Rysunek 9: Krok 1 - dodawanie drugiego elementu do kolejki
Podobnie jak wcześniej można przypisać do niego dowolne dane:
Tmpˆ .DANE := 2 ;
Rysunek 10: Krok 2 - dodawanie drugiego elementu do kolejki
Oraz ustawić wskaźnik na następny element na wartość NIL: Podobnie jak wcześniej można
przypisać do niego dowolne dane:
Tmpˆ . Nastepny := NIL ;
Rysunek 11: Krok 3 - dodawanie drugiego elementu do kolejki
Ponieważ nowy element dodawany jest na końcu kolejki należy go z nią powiązać wykorzystując wskaźnik koniec.
Koniec ˆ . Nastepny := TMP;
5
Rysunek 12: Krok 4 - dodawanie drugiego elementu do kolejki
Ostatnim krokiem jest przypisanie wskaźnikowi koniec adresu ostatnio dodanego elementu:
Koniec := TMP;
Rysunek 13: Krok 5 - dodawanie drugiego elementu do kolejki
W efekcie powstała kolejka zawierająca dwa elementy.
Rysunek 14: Krok 6 - dodawanie drugiego elementu do kolejki
Wszystkie następne elementy dodawane są według takiego samego schematu. Wykorzystując
tą informację oraz wiedzę o tworzeniu pierwszego elementu kolejki można napisać procedurę to
wykonującą. Zwyczajowo procedura ta nosi nazwę ENQUEUE.
3.4
Usuwanie pierwszego elemetnu z kolejki
Usunięcie elementu z kolejki wiąże się z przesunięciem wskaźnika Poczatek na następny element. Poniżej przedstawione zostanie usunięcie elementu z kolejki dwuelementowej utworzonej
w poprzednim przykładzie.
Aby poprawnie usunąć pierwszy element i przesunąć wskaźnik Poczatek należy wykorzystać
dodatkową zmienną tymczasową:
var Tmp: TWskaznikNaStrukture ;
której wartość ustawiamy na początek kolejki:
Tmp := Poczatek ;
6
Rysunek 15: Krok 1 - usuwanie pierwszego elementu z kolejki
Rysunek 16: Krok 2 - usuwanie pierwszego elementu z kolejki
Ponieważ wskaźnik do pierwszego elementu został zapamiętany, można przesunąć wskaźnik
początku na element następny:
Poczatek := Poczatek ˆ . Nastepny ;
Rysunek 17: Krok 3 - usuwanie pierwszego elementu z kolejki
Po przesunięciu wskaźnika początku trzeba zwolnić miejsce w pamięci wykorzystywane przez
usuwany element.
D i s p o s e (Tmp) ;
Rysunek 18: Krok 4 - usuwanie pierwszego elementu z kolejki
Po wykonaniu poprzednich kroków otrzywaliśmy kolejkę jednoelemntową.
7
Rysunek 19: Krok 5 - usuwanie pierwszego elementu z kolejki
Procedura usuwania elementu będzie wyglądała identycznie dla dłuższej kolejki. W przypadku usuwania elementu z kolejki jednoelementowej należy zmienić odpowiednio wskaźnik
Koniec. Poniżej znajduje się procedura zawierająca ten warunek. W literaturze usuwanie elementu kolejki zwyczajowo nazywa się DEQUEUE
8
4
Zadania
1. Zaimplementować funkcje do dodawania i usuwania elementów z kolejki. Uwzględnić
możwliwość wystąpienia błędów.
2. Napisać program odczytujący kolejne znaki z klawiatury i dodające je do kolejki. W przypadku wciśnięcia klawisza Enter kolejkę należy opróżnić a elementy wypisać.
3. Utworzyć program przechowywującą krótkie wiadomości tekstowe wraz z danymi nadawcy. Program powinien pełnić rolę automatycznej sekretarki. Domyślnie powinien wyświetlać zachętę do pozostawienia wiadomości. Na podanie specjalnego hasła ma wyświetlić
kolejne wiadomości.
4. Zaimplementuj kolejkę i jej obsługę, wykorzystującą tylko wskaźnik Poczatek.
5. Zaimplementować kolejkę przechowywującą elementy w tablicy. Utworzyć procedury dodawania i usuwania elementów z takiej kolejki.
9