!"! " #$%& '()#$$ &%$! #$ %$ &%$& &$&! %&'" )$$! *$$&%$! +,- +-.! $ Celem wiczenia jest zapoznanie studenta ze strukturami: lista, stos, drzewo oraz ich implementacja w jzyku ANSI C. Zrozumienie działania tych struktur pozwoli na napisanie programu kalkulatora liczcego w odwrotnej notacji polskiej. /! $'()# Lista to uporzdkowany cig elementów. Przykładami list s wektory lub tablice jednowymiarowe. W wektorach mamy dostp do dowolnego elementu, poprzez podanie indeksu tego elementu. Stos jest list z trzema operacjami: dodawanie elementów na wierzch stosu, zdejmowanie elementu z wierzchu stosu, sprawdzanie czy stos jest pusty. Na stosie dodajemy i odejmujemy elementy z samego koca. Taka organizacja obsługi listy okrelana jest LIFO (ang. last in first out ostatni wszedł, pierwszy wyjdzie). opracowała: mgr in. Izabela Skorupska 1
Struktura reprezentujca element stosu: struct stos char element; struct stos *wskaznik; ; struct stos *wskaznik; Deklaracja elementów stosu: struct stos *nowy, *stary; Procedura realizujca dodawanie elementów na stos: void na_stos(char znak) stary=nowy; nowy= malloc (sizeof(struct stos)); nowy->element=znak; nowy->wskaznik=stary; Procedura realizujca zdejmowanie elementów ze stosu: void ze_stosu(struct stos *wskaz_element) if (wskaz_element!=null) stary=wskaz_element->wskaznik; //printf("usunieto %c ", wskaz_element->element); free(wskaz_element); nowy=stary; Procedura usuwajca wszystkie elementy ze stosu: void oczysc_stos(void) stary=nowy; while (stary!=null) ze_stosu(stary); printf("\nstos oczyszczony."); Procedura drukujca zawarto stosu: void pokaz_stos(void) printf("zawartosc stosu \n"); stary=nowy; while (stary!=null) printf(" %c ", stary->element); stary=stary->wskaznik; Drzewo jest hierarchiczn struktur danych. Pierwszy element drzewa, zwany korzeniem jest wyróniony. Inne elementy s jego potomstwem lub potomstwem jego potomstwa itd. Elementy opracowała: mgr in. Izabela Skorupska 2
drzewa nazywa si wierzchołkami lub wzłami. Licie to wierzchołki nie majce potomstwa. Drzewa czsto przedstawia si w formie grafu, gdzie kady wierzchołek jest połczony krawdzi ze swoim ojcem i ze swoimi dziemi (swoim potomstwem). Dla kadego elementu w drzewie istnieje dokładnie jedna cieka prowadzca od korzenia do tego wierzchołka. Drzewa binarne to takie drzewa, w których kady wierzchołek ma co najwyej dwóch potomków. Struktura reprezentujca drzewo binarne: struct drzewo char element; struct drzewo *prawy; struct drzewo *lewy; ; Drzewa mog by zrównowaone i niezrównowaone. Drzewo jest zrównowaone, gdy rónica wysokoci obu poddrzew kadego wzła w drzewie wynosi 0 lub 1. Szczególnym przypadkiem drzewa niezrównowaonego jest stos.! ($$ Obliczenia arytmetyczne moemy zapisywa w notacji infiksowej, prefiksowej (notacja polska) lub postfiksowej (odwrotna notacja polska). Jeli dodawanie dwóch liczb a i b zapiszemy w postaci: a + b to mamy do czynienia z notacj infiksow, gdy nazwa funkcji została umieszczona pomidzy argumentami. W notacji prefiksowej działanie przybiera posta: + a b natomiast odwrotna notacja polska zostala przedstawiona przez polskiego logika J. Łukasiewicza i działanie opisujemy cigiem: a b + Odwrotna notacja polska jest stosowana w nowoczesnych kalkulatorach naukowych, gdy nie trzeba w niej uywa nawiasów i nie sprawia kłopotów przy wprowadzaniu wielu argumentów. Konwersja bardziej skomplikowanych wyrae przedstawionych w notacji infiksowej do postaci postfiksowej jest kłopotliwa zwłaszcza wtedy, gdy wyraenie oryginalne zawiera wiele zagniedonych nawiasów. 0! '%1$$, ()*)+,! Dla kolejnych zapisów wyraenia: opracowała: mgr in. Izabela Skorupska 3
jeeli element jest stał lub zmienn, to wkładamy jego warto na stos, jeeli element jest znakiem operacji, to: o zdejmujemy dwie wartoci z wierzchu stosu, o wykonujemy operacj na tych wartociach, o obliczon warto wkładamy na wierzch stosu, po przejciu całego wyraenia jego warto znajduje si na stosie. Przykład 1: Dany jest cig w notacji postfiksowej: a b c + * d e / + naley zamieni go w cig zapisany w notacji infiksowej: Krok 1. Kładziemy elementy a b c na stos Krok 2. Wykonujemy działanie + Krok 3. Wykonujemy działanie * Krok 4. Kładziemy elementy d e na stos Krok 5. Wykonujemy działanie / Krok 6. Wykonujemy działanie + Krok 1 Krok 2 Krok 3 Krok 4 Krok 5 Krok 6 c c+b (c+b)*a e e/d e/d+(c+b)*a b a d (c+d)*a a (c+d)*a W wyniku działania algorytmu otrzymamy wyraenie: e/d+(c+b)*a ()-)+, Dla kolejnych zapisów wyraenia, czytajc od koca wyraenia: pierwszy element stanowi wierzchołek drzewa, kolejny element stanowi jego prawego potomka, jeeli wstawiany element jest: o znakiem naley powtórzy operacj 2, o cyfr lub liter, naley wróci do najbliszego wierzchołka i sprawdzi czy ma on ju lewego potomka: jeli nie ma naley go utworzy i powtórzy operacje: 2 i 3, jeli ma wróci do najbliszego wierzchołka nie posiadajcego dwóch potomków i powtórzy operacje: 2 i 3. opracowała: mgr in. Izabela Skorupska 4
Wszystkie operacje wykonujemy do momentu wyczerpania elementów. Przykład 2: Obliczy warto wyraenia: 4 2 3 + * 1 5 - + (metod stosu) Postpujemy zgodnie z opisanym algorytmem: Krok 1 Krok 2 Krok 3 Krok 4 Krok 5 Krok 6 2+3=5 5*4=20 5-1=4 4+20=24 2 5 3 4 1 20 4 20 Przykład 3: Cig: a b c + * d e / + za pomoc drzewa naley zamieni w cig zapisany w notacji infiksowej: Krok 1. Operator + stanowi korze drzewa, / jego prawego potomka. Poniewa / nie jest cyfr ani liter, staje si wierzchołkiem nowej gałzi. Jego prawym liciem bdzie e, które jest liter i nie moe mie swojego potomka. Naley wróci do najbliszego wierzchołka ( / ) i sprawdzi, czy ma on lewego potomka. W realizowanym przykładzie: / go nie ma, wic bdzie nim d. Ten element nie moe by wierzchołkiem nowej gałzi, dlatego szukamy najbliszego wierzchołka, który nie posiada jeszcze dwóch potomków. Warunek ten spełnia korze drzewa. Krok 2. Tworzymy lewego potomka wierzchołka +. Kolejny element cigu stanowi znak opeacji *, zatem moe by on nowym wierzchołkiem. Krok 3. Postpujemy analogicznie jak w kroku 1. Elementy: +, c, b bd stanowiły jego poddrzewo. opracowała: mgr in. Izabela Skorupska 5
Krok 4. Analogicznie jak w kroku 2. Tak zbudowane drzewo bdzie miało posta: Odczytywanie i obliczanie wartoci wyraenia rozpoczynamy od najniszego poziomu (poddrzewa) lewego potomka (od strony prawej do lewej) i wdrujemy ku górze a do wierzchołka, nastpnie powtarzamy operacj dla prawego potomka. Odczytane wyraenie bdzie miało posta: (c+b)*a+(e/d) Przykład 4: Obliczy warto wyraenia: 4 2 3 + * 1 5 - + (metod drzewa) Tworzymy drzewo: Odczytujemy poszczególne składowe wyniku: opracowała: mgr in. Izabela Skorupska 6
2! 3$ Zadanie polega na napisaniu: programu kalkulator.c liczcego warto wyraenia podanego w odwrotnej notacji polskiej (notacji postfiksowej). Załoenia programu kalkulator: program przyjmuje tylko cyfry: 0..9 oraz symbole operacji: * / + - próba wprowadzenia innej wartoci oraz dzielenia przez zero powinna spowodowa wywietlenie odpowiedniego komunikatu i przerwanie operacji liczenia. q oznacza wyjcie z programu dozwolone s dwa sposoby wykonywania oblicze: o za pomoc stosu, o za pomoc drzewa. 4! * Przykładowe uruchomienie programu kalkulator: Wprowadz liczby: 1 2 3 + - Wynik operacji: 4 Wprowadz liczby 1 a + a nie jest cyfra ani znakiem operacji. Wprowadz liczby: 0 1 2 + / Dzielenie przez 0. Wprowadz liczby: q Wyjscie z programu 5! )$ Sprawozdanie powinno zawiera nastpujce elementy: schemat blokowy działania programu, skomentowany plik ródłowy, plik makefile do kompilacji programu, w przypadku wykonywania oblicze na drzewie dokładny opis utworzonej struktury oraz funkcji, wnioski i uwagi. opracowała: mgr in. Izabela Skorupska 7
UWAGA: Program liczcy oparty o operacje wykonywane na drzewie bdzie wyej punktowany ni program wykorzystujcy obliczenia na stosie. 5! 6 1. A. Drozdek, D. L. Simon Struktury danych w jzyku C, WNT 1996. 2. http://julia.univ.gda.pl/~matszp/book/md8.pdf 3. http://galaxy.uci.agh.edu.pl/~chwastek/lectures/c/spis.html opracowała: mgr in. Izabela Skorupska 8