Podstawowe struktury dynamiczne
Transkrypt
Podstawowe struktury dynamiczne
2010-11-10 Podstawowe struktury dynamiczne Algorytmy i struktury danych Wykład 3. Rok akademicki: 2010/2011 Struktura dynamiczna • Struktura dynamiczna – struktura, która: – tworzona jest w programie poprzez jawne użycie odpowiedniej instrukcji (np. operatora new), – może zmieniad swoją wielkośd – liczbę elementów składowych (zmiana ilości zajmowanej pamięci operacyjnej), – jej likwidacja prowadzi do odzyskania zajmowanej przez nią pamięci. 2 1 2010-11-10 Struktury dynamiczne w języku Java • • • • • • • kolekcja (Collection) - grupa obiektów (obiekty mogą się powtarzad), zbiór (Set) - grupa elementów (obiekty nie mogą się powtarzad), zbior posortowany (SortedSet) - jak zbiór, ale kolejnośd elementów jest określona, możliwe jest pobranie następnego lub poprzedniego elementu zbioru (np. uporządkowany alfabetycznie zbiór liter lub zbiór łaocuchów), lista (List) - kolekcja, w której elementy mogą się powtarzad, elementy listy są uporządkowane; dostęp do nich jest również możliwy poprzez indeks. Rodzaje struktur listowych: stos, kolejka, lista jednokierunkowa, lista dwukierunkowa, lista cykliczna, tablica asocjacyjna (Map) – zbiór par (klucz, wartośd), dostęp do elementu jest możliwy po podaniu klucza, posortowana tablica asocjacyjna (SortedMap) - tablica asocjacyjna zawierająca elementy uporządkowane według klucza. drzewa i grafy kolejne wykłady!!! 3 Definicja struktur dynamicznych w postaci interfejsów 4 2 2010-11-10 Interfejs Collection 5 Interfejs Iterator public interface Iterator { boolean hasNext(); Object next(); void remove(); } 6 3 2010-11-10 Wykorzystanie iteratora do usuwania elementów Collection collection = ...; Iterator iterator = collection.iterator(); while (iterator.hasNext()) { Object element = iterator.next(); if (removalCheck(element)) { iterator.remove(); } } 7 Klasa AbstractCollection • public abstract class AbstractCollection extends Object implements Collection • przy tworzeniu kolekcji niezbędne jest: – – – – określenie sposobu przechowywania danych zdefiniowanie metody iterator() zdefiniowanie metody size() zdefiniowanie metody add() - dostępna metoda add() generuje wyjątek UnsupportedOperationException – zdefiniowanie konstruktorów: Kolekcja() oraz Kolekcja(Collection c) 8 4 2010-11-10 Kolekcja – przykład 1/6 import java.util.Collection; import java.util.AbstractCollection; import java.util.Iterator; import java.util.NoSuchElementException; class KolekcjaLiterA extends AbstractCollection implements Iterator { private int ileLiter; private int aktualnaLitera; private boolean czyMoznaUsunac; KolekcjaLiterA() { ileLiter = 0; czyMoznaUsunac = false; aktualnaLitera = 0; } 9 Kolekcja – przykład 2/6 KolekcjaLiterA(Collection c) { addAll(c); } public Iterator iterator() { aktualnaLitera = 0; return this; } public boolean hasNext() { return (aktualnaLitera < ileLiter); } 10 5 2010-11-10 Kolekcja – przykład 3/6 public Object next() { if (aktualnaLitera < ileLiter) { aktualnaLitera++; czyMoznaUsunac = true; return new Character('A'); } else { czyMoznaUsunac = false; throw new NoSuchElementException("Brak nastepnego elementu"); } } 11 Kolekcja – przykład 4/6 public void remove() { if (czyMoznaUsunac) { ileLiter--; czyMoznaUsunac = false; } } public int size() { return ileLiter; } public boolean add(Object o) { if(o == null) throw new NullPointerException("Pusty wskaznik"); if(!(o instanceof Character)) throw new ClassCastException("Tylko obiekty typu Character"); Character znak = (Character) o; if (znak.charValue() != 'A') throw new IllegalArgumentException("Tylko A"); ileLiter++; return true; } 12 6 2010-11-10 Kolekcja – przykład 5/6 public String toString() { StringBuffer buf = new StringBuffer(); for (int i = 0; i < size(); i++) buf.append('A'); return buf.toString(); } } 13 Kolekcja – przykład 6/6 public class TestKolekcjiLiterA { public static void main(String [] args) { KolekcjaLiterA pierwsza = new KolekcjaLiterA(); pierwsza.add(new Character('A')); pierwsza.add(new Character('A')); System.out.println("Pierwsza kolekcja: " + pierwsza); KolekcjaLiterA druga= new KolekcjaLiterA(); druga.add(new Character('A')); druga.add(new Character('A')); druga.add(new Character('A')); druga.add(new Character('A')); System.out.println("Druga kolekcja: " + druga); druga.removeAll(pierwsza); System.out.println("Druga kolekcja: " + druga); druga.add(new Character('A')); System.out.println("Druga kolekcja: " + druga); KolekcjaLiterA trzecia = new KolekcjaLiterA(druga); System.out.println("Trzecia kolekcja: " + trzecia); } } 14 7 2010-11-10 Interfejs Set 15 Elementy w zbiorze nie mogą się powtarzad! • Do sprawdzenia, czy dany element występuje w zbiorze służy zdefiniowana w klasie Object metoda: public boolean equals(Object obj) • implementacja zawarta w klasie Object sprawdza, czy referencja do bieżącego obiektu jest równa referencji do obiektu reprezentowanego przez parametr (czyli, czy te dwa obiektu zajmują to samo miejsce w pamięci) – dla klas definiowanych przez programistę zwykle konieczne jest zredefiniowanie metody equals. 16 8 2010-11-10 Klasa AbstractSet • public abstract class AbstractSet extends AbstractCollection implements Set • Klasa AbstractSet jest wykorzystywana w podobny sposób jak klasa AbstractCollection. 17 Klasa HashSet - implementacja zbioru import java.util.*; public class PrzykladZbioru { public static void main(String args[]) { Set set = new HashSet(); set.add("Wiosna"); set.add("Lato"); set.add("Jesien"); set.add("Zima"); set.add("Zima"); set.add("Zima"); set.add("Zima"); System.out.println(set); Wynik działania programu: [Jesien, Wiosna, Zima, Lato] [Jesien, Wiosna, Zima] set.remove("Lato"); System.out.println(set); } } 18 9 2010-11-10 Implementacja zbiorów typu HashSet • Do przechowywania elementów zbioru typu HashSet wykorzystywana jest struktura danych nazywana tablicą z haszowaniem. • Podstawowe cechy tablicy z haszowaniem: – pozwala na szybki dostęp do jej elementów składowych, – pozwala na efektywne zarządzanie pamięcią operacyjną. – W tablicy z haszowaniem mogą byd przechowywane obiekty, dla których można wyznaczyd wartośd klucza. 19 Cechy klucza haszującego (skrótu) • • • • • klucz jest liczbą całkowitą, wartośd klucza jest uzależniona od wartości przechowywanych w obiekcie; dwa identyczne obiekty (ze względu na metodę equals – czyli tego samego typu i przechowujące takie same wartości) mają identyczne wartości kluczy; dwa różne obiekty mogą posiadad identyczne lub różne wartości kluczy (zaleca się, aby były one różne) w języku Java do wyznaczenia wartości klucza służy funkcja z klasy Object: public int hashCode() • funkcja hashCode jest dziedziczona przez wszystkie inne klasy (może byd redefiniowana) 20 10 2010-11-10 Funkcja hashCode() dla klasy String s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] class Test { public static void main(String [] args) { String s = "Java"; System.out.println(s.hashCode()); } } Efekt działania: 2301506 21 Funkcja hashCode() w klasie Object • funkcja hashCode() zdefiniowana w klasie Object zwraca informację o położeniu obiektu (adres obiektu przekształcony do wartości typu int) – zwykle dla klas definiowanych przez programistę konieczna jest redefinicja, gdyż nie jest spełniony warunek głoszący, że równe obiekty (equals) posiadają identyczne kody • jeśli obiekty mają byd przechowywane w zbiorze typu HashSet to muszą mied poprawnie zdefiniowaną funkcję hashCode(). 22 11 2010-11-10 Struktura tablicy z haszowaniem funkcja haszująca: hashCode() % n gdzie: n – liczba elementów w wektorze 23 Przykład 1/4 import java.util.*; class Lancuch { String s; Lancuch(String s) { this.s = s; } public String toString() { return s; } } 24 12 2010-11-10 Przykład 2/4 public class Test { public static void main(String args[]) { Set set = new HashSet(); set.add(new Lancuch("Szczecin")); set.add(new Lancuch("Olsztyn")); set.add(new Lancuch("Opole")); set.add(new Lancuch("Katowice")); set.add(new Lancuch("Katowice")); System.out.println(set); } } 25 Przykład 3/4 Efekt działania programu: [Olsztyn, Szczecin, Katowice, Opole, Katowice] WYNIK JEST BŁĘDNY – W ZBIORZE WYSTĘPUJĄ DWA IDENTYCZNE ELEMENTY!!! Konieczna jest modyfikacja klasy Lancuch 26 13 2010-11-10 Przykład 4/4 class Lancuch { String s; Lancuch(String s) { this.s = s; } public String toString() { return s; } public boolean equals(Object obj) { if (!(obj instanceof Lancuch)) return false; if (((Lancuch) obj).s.equals(s)) return true; else return false; } public int hashCode() { return s.hashCode(); } } Efekt działania programu: [Szczecin, Katowice, Opole, Olsztyn] 27 Interfejs SortedSet Interfejs SortedSet implementowany jest przez klasę TreeSet. 28 14 2010-11-10 Interfejs Comparable Operację porządkowania elementów definiuje interfejs Comparable Porównuje dany obiekt z obiektem reprezentowanym przez parametr i zwraca: • wartośd ujemną, jeśli dany obiekt jest mniejszy, • zero, jeśli są równe, • wartośd dodatnią, jeśli dany obiekt jest większy. Jeśli elementami zbioru typu TreeSet są obiekty implementujące interfejs Comparable, to są one porządkowane zgodnie ze sposobem działania metody compareTo(). 29 Przykład 1/2 import java.util.*; public class PrzykladZbioru { public static void main(String args[]) { Set set = new TreeSet(); set.add("Wiosna"); set.add("Lato"); set.add("Jesien"); set.add("Zima"); 30 15 2010-11-10 Przykład 2/2 System.out.println(set); set.remove("Lato"); System.out.println(set); } } Efekt działania programu: [Jesien, Lato, Wiosna, Zima] 31 Interfejs Comparator Jeśli elementami zbioru mają byd obiekty, które nie implementują interfejsu Comparable, to sposób ich porównania dokonywany jest za pomocą metod interfejsu Comparator. Utworzony obiekt pozwalający na porównanie elementów zbioru (komparator) jest przekazywany jako parametr konstruktora obiektu TreeSet. 32 16 2010-11-10 Przykład 1/2 import java.util.*; class PorownajDlugosciTekstow implements Comparator { public int compare(Object element1, Object element2) { int dlugosc1 = ((String) element1).length(); int dlugosc2 = ((String) element2).length(); return dlugosc1 - dlugosc2; } } 33 Przykład 2/2 public class Porownania { public static void main(String [] args) { PorownajDlugosciTekstow p = new PorownajDlugosciTekstow(); TreeSet zbior = new TreeSet(p); zbior.add("Andrzej"); zbior.add("Basia"); zbior.add("Jan"); zbior.add("Boleslaw"); System.out.println(zbior); } } Wynik działania programu: [Jan, Basia, Andrzej, Boleslaw] 34 17 2010-11-10 Implementacja zbioru typu TreeSet 10 5 14 7 12 18 15 Zbiory typu TreeSet przechowywane są w postaci drzewa poszukiwao binarnych - Dla każdego węzła, wszystkie elementy jego lewego poddrzewa (jeżeli takie istnieją) reprezentują elementy mniejsze od elementu reprezentowanego przez ten węzeł, zaś wszystkie elementy jego prawego poddrzewa (jeżeli takie istnieją) reprezentują elementy większe od elementu reprezentowanego przez rozpatrywany węzeł. 35 Reprezentacja struktur listowych 36 18 2010-11-10 Listy • kolekcja uporządkowanych elementów (z możliwością powtórzeo); • elementy listy są ponumerowane (od zera); • podstawowe cechy listy opisane są w interfejsie List. 37 Interfejs List 38 19 2010-11-10 Interfejs ListIterator 39 Implementacja list w języku Java • ArrayList - implementacja interfejsu List jako wektora o zmieniających się wymiarach • LinkedList - implementacja interfejsu List jako struktury listowej. 40 20 2010-11-10 Klasa ArrayList • Elementy listy przechowywane są wektorze • w przypadku braku miejsca w wektorze tworzony jest nowy wektor o wielkości: nnowy = 1,5 * nstary + 1 do którego kopiowane są elementy z dotychcza-sowego wektora; po przekopiowaniu dotychczasowy wektor jest usuwany z pamięci. 41 Zastosowania klasy ArrayList • stosowanie list typu ArrayList jest zalecane wtedy, gdy: – często zachodzi potrzeba odwoływania się do elementów listy, – rzadko zachodzi potrzeba modyfikacji wielkości listy. 42 21 2010-11-10 ArrayList – przykładowy program import java.util.*; public class Wektor { public static void main(String[] args) { ArrayList w = new ArrayList(5); for (int i = 1; i <= 10; i++) w.add(new Integer(i)); //wyswietlenie wektora System.out.println("Wektor: " + w); 43 ArrayList – przykładowy program //korzystanie z ListIteratora ListIterator iter = w.listIterator(0); while (iter.hasNext()) if (((Integer) iter.next()).intValue() % 2 != 0) iter.remove(); //wyswietlenie wektora System.out.println("Wektor: " + w); } } 44 22 2010-11-10 Klasa LinkedList lista typu LinkedList przechowywana jest jako lista dwukierunkowa, 45 Zastosowanie klasy LinkedList • stosowanie listy typu LinkedList jest zalecane wtedy, gdy: – rzadko zachodzi potrzeba odwoływania się do elementów listy za pomocą indeksów, – często zachodzi potrzeba dodawania i usuwania elementów znajdujących się na liście. 46 23 2010-11-10 Klasa LinkedList – przykład 1/3 import java.util.*; public class LiczbyPierwsze { static boolean czyPierwsza(int liczba) { for (int i = 2; i <= Math.min( (int) Math.sqrt(liczba) + 1,liczba-1); i++) if (liczba % i == 0) return false; return true; } 47 Klasa LinkedList – przykład 2/3 public static void main(String[] args) { LinkedList lista = new LinkedList(); for (int i = 1; i <= 20; i++) lista.add(new Integer(i)); System.out.println("Lista: " + lista); ListIterator iter = lista.listIterator(); Integer element; while (iter.hasNext()) if (czyPierwsza((element = (Integer) iter.next()).intValue())) iter.set("{" + element.intValue() + "}"); System.out.println("Lista: " + lista); iter = lista.listIterator(); while (iter.hasNext()) if (!(iter.next() instanceof String)) iter.remove(); System.out.println("Lista: " + lista); } } 48 24 2010-11-10 Klasa LinkedList – przykład 3/3 • Efekt działania programu: Lista: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] Lista: [{1}, {2}, {3}, 4, {5}, 6, {7}, 8, 9, 10, {11}, 12, {13}, 14, 15, 16, {17}, 18, {19}, 20] Lista: [{1}, {2}, {3}, {5}, {7}, {11}, {13}, {17}, {19}] 49 LinkedList jako stos oraz jako kolejka • metody zdefiniowane w klasie LinkedList pozwalające na wykorzystanie obiektu w charakterze stosu lub kolejki (metody te nie są częścią interfejsu List) 50 25 2010-11-10 Stos wierzchołek stosu 51 Stos – przykładowy program 1/3 import java.util.*; public class Stos { public static void main(String[] args) { LinkedList st = new LinkedList(); st.addFirst("Poniedzialek"); st.addFirst("Wtorek"); st.addFirst("Sroda"); //sprawdzenie elementu znajdujacego się //na wierzcholku stosu (bez usuwania go ze stosu) System.out.println("Na wierzcholku stosu znajduje sie: " + st.getFirst()); 52 26 2010-11-10 Stos – przykładowy program 2/3 //wyswietlenie stosu System.out.println("Elementy: " + st); //pobieranie elementow ze stosu (z usuwaniem) System.out.println("\nPobieranie elementow ze stosu\n"); while(!st.isEmpty()) { System.out.println(" Pobrany element to: " + st.removeFirst()); System.out.println(" Zawartosc stosu: " + st); System.out.println(); } } } 53 Stos – przykładowy program 3/3 Efekt działana programu: Na wierzcholku stosu znajduje sie: Sroda Elementy: [Sroda, Wtorek, Poniedzialek] Pobieranie elementow ze stosu Pobrany element to: Sroda Zawartosc stosu: [Wtorek, Poniedzialek] Pobrany element to: Wtorek Zawartosc stosu: [Poniedzialek] Pobrany element to: Poniedzialek Zawartosc stosu: [] 54 27 2010-11-10 Kolejka początek kolejki koniec kolejki 55 Kolejka – przykładowy program 1/4 import java.util.*; public class Kolejka { public static void main(String[] args) { LinkedList kol = new LinkedList(); kol.addLast("Poniedzialek"); kol.addLast("Wtorek"); kol.addLast("Sroda"); 56 28 2010-11-10 Kolejka – przykładowy program 2/4 //sprawdzenie elementu znajdujacego się //na poczatku kolejki (bez usuwania go z kolejki) System.out.println("Na poczatku kolejki znajduje sie:" + kol.getFirst()); //wyswietlenie kolejki System.out.println("Elementy: " + kol); //pobieranie elementow z kolejki (z usuwaniem) System.out.println("\nPobieranie elementow z kolejki\n"); 57 Kolejka – przykładowy program 3/4 while(!kol.isEmpty()) { System.out.println(" Pobrany element to: " + kol.removeFirst()); System.out.println(" Zawartosc kolejki: " + kol); System.out.println(); } } } 58 29 2010-11-10 Kolejka – przykładowy program 4/4 Efekt działania programu: Na poczatku kolejki znajduje sie: Poniedzialek Elementy: [Poniedzialek, Wtorek, Sroda] Pobieranie elementow z kolejki Pobrany element to: Poniedzialek Zawartosc kolejki: [Wtorek, Sroda] Pobrany element to: Wtorek Zawartosc kolejki: [Sroda] Pobrany element to: Sroda Zawartosc kolejki: [] 59 Tablica asocjacyjna • tablica asocjacyjna: kolekcja par: klucz - wartośd (wartości klucza nie mogą się powtarzad), • tablica asocjacyjna jest opisana za pomocą interfejsu Map. 60 30 2010-11-10 Interfejsy Map oraz Map.Entry metoda entrySet zwraca zbiór elementów tablicy asocjacyjnej. Każdy element implementuje interfejs Map.Entry. 61 Implementacja tablic asocjacyjnych • Tablice asocjacyjne zaimplementowane są w postaci klas: – HashMap – TreeMap – uporządkowana tablica asocjacyjna 62 31 2010-11-10 Klasa HashMap • do przechowywania kluczy stosowana jest tablica z haszowaniem; w związku z tym obiekty spełniające rolę kluczy muszą posiadad prawidłowo zaimplementowaną funkcję hashCode() oraz equals(). • klucze nie mogą się powtarzad; • przeszukiwanie zbioru kluczy jest znacznie szybsze niż przeszukiwanie zbioru obiektów. 63 HashMap – przykład 1/4 import java.util.*; public class TablicaAsocjacyjna { public static void main(String [] args) { Map asoc = new HashMap(); asoc.put(new Integer(1),"Jeden"); asoc.put(new Integer(2),"Dwa"); asoc.put(new Integer(3),"Trzy"); asoc.put(new Integer(4),"Cztery"); asoc.put(new Integer(5),"Piec"); System.out.println("Tablica asocjacyjna: " + asoc); 64 32 2010-11-10 HashMap – przykład 2/4 System.out.println("czy jest klucz '44' - " + asoc.containsKey(new Integer(44))); System.out.println("czy jest klucz '1' - " + asoc.containsKey(new Integer(1))); System.out.println("element o kluczu '44': " + asoc.get(new Integer(44))); System.out.println("element o kluczu '1': " + asoc.get(new Integer(1))); System.out.println("czy jest wartosc 'Dwa': " + asoc.containsValue("Dwa")); System.out.println("czy jest wartosc 'Siedem': " + asoc.containsValue("Siedem")); 65 HashMap – przykład 3/4 Set zawartosc = asoc.entrySet(); Iterator iter = zawartosc.iterator(); Map.Entry element; System.out.println("\nZawartosc tablicy asocjacyjnej\n"); while(iter.hasNext()) { element = (Map.Entry) iter.next(); System.out.print("klucz=" + element.getKey()); System.out.println(" wartosc=" + element.getValue()); } } } 66 33 2010-11-10 HashMap – przykład 4/4 Efekt działania programu: Tablica asocjacyjna: {2=Dwa, 4=Cztery, 1=Jeden, 3=Trzy, 5=Piec} czy jest klucz '44' - false czy jest klucz '1' - true element o kluczu '44': null element o kluczu '1': Jeden czy jest wartosc 'Dwa': true czy jest wartosc 'Siedem': false Zawartosc tablicy asocjacyjnej klucz=2 wartosc=Dwa klucz=4 wartosc=Cztery klucz=1 wartosc=Jeden klucz=3 wartosc=Trzy klucz=5 wartosc=Piec 67 Klasa TreeMap • elementy uporządkowane są według wartości kluczy • do przechowania kluczy wykorzystywane jest drzewo poszukiwao binarnych • Porządkowanie obiektów: – naturalne (kluczami są obiekty implementujące interfejs Comparable), – zdefiniowane za pomocą komparatora 68 34 2010-11-10 Porządkowanie naturalne import java.util.*; public class TreeMapTest1 { public static void main(String [] args) { Map kraje = new TreeMap(); kraje.put("Niemcy","Berlin"); kraje.put("Polska","Warszawa"); kraje.put("Czechy","Praga"); kraje.put("Hiszpnia","Madryt"); kraje.put("Grecja","Ateny"); kraje.put("Wlochy","Rzym"); System.out.println(kraje); } } Wyniki działania programu: {Czechy=Praga, Grecja=Ateny, Hiszpnia=Madryt, Niemcy=Berlin, Polska=Warszawa, Wlochy=Rzym} 69 Zastosowanie komparatora 1/2 import java.util.*; class Porzadkowanie implements Comparator { public int compare(Object o1, Object o2) { return -1 * ((String) o1).compareTo((String) o2); } } 70 35 2010-11-10 Zastosowanie komparatora 2/2 public class TreeMapTest2 { public static void main(String [] args) { Porzadkowanie p = new Porzadkowanie(); Map kraje = new TreeMap(p); kraje.put("Niemcy","Berlin"); kraje.put("Polska","Warszawa"); kraje.put("Czechy","Praga"); kraje.put("Hiszpnia","Madryt"); kraje.put("Grecja","Ateny"); kraje.put("Wlochy","Rzym"); System.out.println(kraje); } } Wyniki działania programu: {Wlochy=Rzym, Polska=Warszawa, Niemcy=Berlin, Hiszpnia=Madryt, Grecja=Ateny, Czechy=Praga} 71 Wyznaczanie wartości wyrażenia przy wykorzystaniu ONP • Sposób realizacji obliczeo: – określenie postaci wyrażenia, – przekształcenie wyrażenia do postaci równoważnej zapisanej za pomocą Odwrotnej Notacji Polskiej (ONP), – sprawdzenie poprawności wyrażenia zapisanego w ONP, – wyznaczenie wartości wyrażenia zapisanego w ONP. • Podstawową strukturą danych wykorzystywaną w trakcie obliczeo jest stos. 72 36 2010-11-10 Odwrotna Notacja Polska • Twórcą jest Jan Łukasiewicz, 1921 • ONP jest notacją postfiksową (operator podawany jest po argumentach) • Przykłady wyrażeo w notacji infiksowej i postfiksowej: A+BAB+ (B - C) * D B C - D * 73 Konwersja do postaci postfiksowej • Podstawowe zasady obowiązujące w trakcie konwersji: – Kolejnośd argumentów w postaci infiksowej i postfiksowej jest taka sama. – Zmianie ulega kolejnośd operatorów. – Wyrażenie w postaci infiksowej jest analizowane od lewej do prawej strony. – Po odczytaniu argumentu jest on natychmiast zapisywany do wyrażenia w postaci postfiksowej. – Odczytane operatory przechowywane są na stosie. 74 37 2010-11-10 Konwersja do postaci postfiksowej • Algorytm konwersji: 1. 2. 3. 4. Usunięcie wszystkich elementów ze stosu (na początku konwersji stos musi byd pusty). Jeżeli odczytany został operator i stos jest pusty to operator jest umieszczany na stosie. Jeżeli odczytany został operator o wyższym priorytecie niż operator znajdujący się na wierzchołku stosu to odczytany operator jest umieszczany na stosie. W przeciwnym przypadku ze stosu usuwany jest operator znajdujący się na jego wierzchołku i umieszczany jest on na koocu wyrażenia w postaci postfiksowej. Dalszy sposób postępowania z odczytanym operatorem jest określony przez ponowna realizację punktu 2 lub punktu 3. Jeżeli został osiągnięty koniec analizowanego wyrażenia zapisanego w postaci infiksowej to ze stosu usuwane są kolejno znajdujące się tam operatory i są dopisywane do wyrażenia w postaci postfiksowej. 75 Analiza przykładowego wyrażenia 76 38 2010-11-10 Wyrażenia z nawiasami 1. Jeżeli odczytanym elementem wyrażenia zapisanego w postaci infiksowej jest lewy nawias to jest on umieszczany na stosie. Nawiasy traktowane są w podobny sposób jak operatory. Priorytet nawiasu jest niższy od priorytetu każdego innego operatora. 2. Jeżeli odczytanym elementem wyrażenia zapisanego w postaci infiksowej jest prawy nawias to ze stosu usuwane są kolejno znajdujące się na nim operatory i dopisywane są one do wyrażenia w postaci postfiksowej. Operacja usuwania operatorów ze stosu jest wykonywana aż do chwili, gdy na wierzchołku stosu znajdzie się lewy nawias. Wówczas odpowiadające sobie nawiasy są usuwane (prawy z wyrażenia infiksowego, zaś lewy ze stosu). 77 Przykład 1/3 78 39 2010-11-10 Przykład 2/3 79 Przykład 3/3 80 40 2010-11-10 Ranga wyrażenia • Przez stopieo operatora rozumie się liczbę wymaganych przez niego argumentów (np. stopieo operatora * wynosi 2). • Każdemu wyrażeniu postfiksowemu można przypisad współczynnik zwany rangą wyrażenia. • Sposób obliczania rangi: 1. 2. 3. Ranga symbolu (wartości występującej w wyrażeniu) wynosi 1. Ranga operatora n-tego stopnia wynosi 1 - n. Ranga ciągu symboli i operatorów jest równa sumie rang poszczególnych symboli i operatorów. 81 Poprawnośd wyrażenia arytmetycznego • Konwersja błędnie zapisanego wyrażenia w postaci infiksowej prowadzi do utworzenia błędnego wyrażenia w postaci postfiksowej. • Procedura sprawdzająca poprawnośd wyrażenia może analizowad wyłącznie postad postfiksową. • Wyrażenie postfiksowe jest poprawne wtedy i tylko wtedy, gdy ranga tego wyrażenia jest równa 1 i ranga dowolnej głowy właściwej wyrażenia jest większa lub równa 1. 82 41 2010-11-10 Poprawnośd przykładowych wyrażeo Infix: a - b * c Postfix: a b c * poprawny Infix: a + * b Postfix: a b * + błędny Infix: a*+bc Postfix: a * bc+ błędny 83 Wartośd wyrażenia w ONP • W trakcie analizy wyrażenia od lewej do prawej strony: – odczytane argumenty są umieszczane na stosie, – po odczytaniu operatora odczytywana jest ze stosu odpowiednia liczba argumentów, wykonywane jest działanie i wynik umieszczany jest ponownie na stosie. 84 42 2010-11-10 Wartośd przykładowego wyrażenia 85 43