Algorytmy i. Wykład 3: Stosy, kolejki i listy. Dr inż. Paweł Kasprowski. FIFO First In First Out (kolejka) LIFO Last In First Out (stos)



Podobne dokumenty
Dynamiczny przydział pamięci w języku C. Dynamiczne struktury danych. dr inż. Jarosław Forenc. Metoda 1 (wektor N M-elementowy)

Podstawy informatyki 2. Podstawy informatyki 2. Wykład nr 2 ( ) Plan wykładu nr 2. Politechnika Białostocka. - Wydział Elektryczny

Podstawy informatyki 2

Wstęp do programowania

Algorytmy i Struktury Danych.

Kiedy potrzebne. Struktura (rekord) Struktura w języku C# Tablice struktur. struktura, kolekcja

Struktury danych: stos, kolejka, lista, drzewo

Struktury. Przykład W8_1

Algorytmy i Struktury Danych.

Wykład 4. Klasa List Kolejki Stosy Słowniki

Algorytmy i Struktury Danych.

Odwrotna Notacja Polska

Programowanie i struktury danych 1 / 44

Wykład 5 Wybrane zagadnienia programowania w C++ (c.d.)

Lista, Stos, Kolejka, Tablica Asocjacyjna

Marcin Matusiak i Łukasz Stasiak

dr inż. Paweł Myszkowski Wykład nr 11 ( )

Dynamiczne struktury danych

Algorytmy i. Wykład 5: Drzewa. Dr inż. Paweł Kasprowski

Programowanie w języku Java. Kolekcje

Algorytmy i Struktury Danych. Co dziś? Drzewo decyzyjne. Wykład IV Sortowania cd. Elementarne struktury danych

Kurs programowania. Wykład 9. Wojciech Macyna

Materiał uzupełniający do ćwiczen z przedmiotu: Programowanie w C ++ - ćwiczenia na wskaźnikach

Programowanie obiektowe

Programowanie w Javie Lista nr 1. Wybieramy kategorię Java, a wśród Projektów Java Application i [NEXT]

Wykład 4: Klasy i Metody

Podstawowe struktury danych

Pętle while, for, do while, instrukcje break, continue, switch 1. Pętle

Listy, kolejki, stosy


Laboratorium 03: Podstawowe konstrukcje w języku Java [2h]

Kurs programowania. Wykład 9. Wojciech Macyna. 28 kwiecień 2016

Notacja RPN. 28 kwietnia wyliczanie i transformacja wyrażeń. Opis został przygotowany przez: Bogdana Kreczmera.

Dynamiczny przydział pamięci (język C) Dynamiczne struktury danych. Sortowanie. Klasyfikacja algorytmów sortowania. Algorytmy sortowania

INFORMATYKA. Podstawy programowania w języku C. (Wykład) Copyright (C) 2005 by Sergiusz Sienkowski IME Zielona Góra

Szablony klas, zastosowanie szablonów w programach

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

E S - uniwersum struktury stosu

Podstawy programowania obiektowego

Struktura danych. Sposób uporządkowania informacji w komputerze. Na strukturach danych operują algorytmy. Przykładowe struktury danych:

Język JAVA podstawy. Wykład 3, część 3. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Obliczenia na stosie. Wykład 9. Obliczenia na stosie. J. Cichoń, P. Kobylański Wstęp do Informatyki i Programowania 266 / 303

Wstęp do programowania

Metody Metody, parametry, zwracanie wartości

Wskaźniki i dynamiczna alokacja pamięci. Spotkanie 4. Wskaźniki. Dynamiczna alokacja pamięci. Przykłady

Język JAVA podstawy. wykład 2, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

INFORMATYKA W SZKOLE. Podyplomowe Studia Pedagogiczne. Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227

Programowanie w C++ Wykład 3. Katarzyna Grzelak. 12 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 35

Języki i metody programowania Java INF302W Wykład 2 (część 1)

Struktura danych. Sposób uporządkowania informacji w komputerze. Na strukturach danych operują algorytmy. Przykładowe struktury danych:

Abstrakcyjne struktury danych w praktyce

Wykład 4. Tablice. Pliki

Języki i metody programowania Java INF302W Wykład 3 (część 1)

Tworzenie aplikacji w języku Java

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Programowanie i struktury danych

Podstawy i języki programowania

Programowanie obiektowe

Informatyka 2. Wykład nr 5 ( ) Plan wykładu nr 5. Politechnika Białostocka. - Wydział Elektryczny. Odwrotna notacja polska.

Informatyka 2. Wykład nr 5 ( ) Politechnika Białostocka. - Wydział Elektryczny. dr inŝ. Jarosław Forenc

Wykład 6_1 Abstrakcyjne typy danych stos Realizacja tablicowa i za pomocą rekurencyjnych typów danych

Co to jest sterta? Sterta (ang. heap) to obszar pamięci udostępniany przez system operacyjny wszystkim działającym programom (procesom).

Zofia Kruczkiewicz, Programowanie obiektowe - java, wykład 2 1

Zasady programowania Dokumentacja

Stos LIFO Last In First Out

Algorytmy i Struktury Danych

Wykład 8: Obsługa Wyjątków

Języki i techniki programowania Ćwiczenia 2

Wskaźniki. Przemysław Gawroński D-10, p marca Wykład 2. (Wykład 2) Wskaźniki 8 marca / 17

Techniki programowania INP001002Wl rok akademicki 2018/19 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Wybrane algorytmy tablicowe

Algorytmy i złożoności Wykład 5. Haszowanie (hashowanie, mieszanie)

Struktury Danych i Złożoność Obliczeniowa

Języki i Techniki Programowania II. Wykład 7. Współbieżność 1

Stos liczb całkowitych

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

Wykład 2: Podstawy Języka

Kolekcje - pakiet Java Collections Framework

- - Ocena wykonaniu zad3. Brak zad3

Konstruktory. Streszczenie Celem wykładu jest zaprezentowanie konstruktorów w Javie, syntaktyki oraz zalet ich stosowania. Czas wykładu 45 minut.

Podejście obiektowe. Tablice (1) obiektów

KOLEJKA (QUEUE) (lista fifo first in, first out)

Programowanie obiektowe

Programowanie i projektowanie obiektowe

Język programowania: Lista instrukcji (IL Instruction List)

Programowanie obiektowe

Algorytmy i Struktury Danych.

Podstawy programowania. Wykład 6 Złożone typy danych: struktury, unie. Krzysztof Banaś Podstawy programowania 1

dr inż. Piotr Czapiewski Tworzenie aplikacji w języku Java Laboratorium 1

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Dynamiczne struktury danych

ZASADY PROGRAMOWANIA KOMPUTERÓW

Realizacja ekstensji klasy. Paulina Strzelecka, Tomasz Roszkowski

WYKŁAD 8. Funkcje i algorytmy rekurencyjne Proste przykłady. Programy: c3_1.c..., c3_6.c. Tomasz Zieliński

Kurs programowania. Wykład 3. Wojciech Macyna. 22 marca 2019

Teoretyczne podstawy informatyki

Wykład 3. Złożoność i realizowalność algorytmów Elementarne struktury danych: stosy, kolejki, listy

Definiowanie własnych klas

1. Kalkulator czterech działań. 2. Konwersja ciągu znaków do tablicy.

Transkrypt:

Algorytmy i struktury danych Wykład 3: Stosy, kolejki i listy Dr inż. Paweł Kasprowski pawel@kasprowski.pl Kolejki FIFO First In First Out (kolejka) LIFO Last In First Out (stos) Stos (stack) Dostęp jedynie do wierzchołka stosu (elementu, który leży na szczycie) Metody: push() wstaw na stos pop() pobierz ze stosu Ograniczenie dostępu do elementów ułatwia użytkowanie stosu Stos może być przechowywany w dowolnej strukturze (na razie przykład z tablicą) 1

Wstawianie elementu public void push(int wartosc) { tablica[nelem]=wartosc; nelem++; Kod identyczny jak metody wstaw() W rzeczywistości stos nie musi być implementowany jako tablica! Pobieranie elementu public int pop() { nelem--; return tablica[nelem]; Zawsze pobiera ostatni element (ostatnio włożony na stos) i "zwalnia" miejsce Wykorzystanie stosu Obracanie słów Sprawdzanie nawiasów Obliczanie wyrażeń algebraicznych 2

Klasa Stack class Stack { char[ ] tablica; int nelem; public void push(char h wartosc) { tablica[nelem]=wartosc; nelem++; public char pop() { nelem--; return tablica[nelem]; Klasa StackMain static public void main(string[] args) { System.out.println("Podaj tekst:"); String txt = getstring(); String txt2 = reverse(txt); System.out.println("Przed obrotem: "+txt); System.out.println("Po obrocie: "+txt2); Funkcja getstring public static String getstring() throws IOException { InputStreamReader isr = new InputStreamReader(System.in); BufferedReader br = new BufferedReader(isr); String s = br.readline(); return s; Pobiera tekst ze standardowego wejścia Charakterystyczna dla Javy nie będziemy jej analizować, tylko używać 3

Funkcja reverse public static String reverse(string txt) { Stack stos = new Stack(txt.length()); // stworzenie stosu for(int i=0;i<txt.length();i++) stos.push(txt.charat(i)); t h // wrzucenie kolejnych liter String txt2 = ""; // zmienna pomocnicza while(stos.size()>0) txt2+=stos.pop();// ściągnięcie liter (kolejność odwrotna) return txt2; StackMain.java Sprawdzanie nawiasów Trzy rodzaje nawiasów: okrągłe ( ) klamrowe { kwadratowe [ ] Wprowadzony tekst powinien zawierać znaki otwarcia i zamknięcia wszystkich nawiasów Nawiasy są zawsze zagnieżdżone ( { ( ) ) OK ( { ) źle Oprócz nawiasów mogą występować dowolne inne znaki Algorytm Przeglądaj wprowadzony tekst Jeśli nawias otwierający wrzuć na stos Jeśli nawias zamykający ściągnij nawias otwierający ze stosu jeśli nawiasy nie odpowiadają sobie lub stos pusty zakończ zgłaszając błąd Jeśli inny znak pomiń Jeśli koniec ciągu zakończ zgłaszając poprawność 4

Implementacja for(int i=0;i<txt.length();i++) { // dla kolejnych znaków char znak = txt.charat(i); if(znak=='(' znak=='[' znak=='{') // jeśli nawias otwierający stos.push(znak); // wrzuć na stos if(znak==')' znak==']' znak=='') // jeśli nawias zamykający if(stos.size()==0) size()==0) // stos pusty - błąd System.out.println("Błąd na pozycji "+i); else { char x = stos.pop(); if( (x=='{' && znak!='') (x=='[' && znak!=']') (x=='(' && znak!=')') ) // na stosie inny nawias - błąd System.out.println("Błąd na pozycji "+i); Funkcja check public static void check(string txt) { Stack stos = new Stack(txt.length()); for(int i=0;i<txt.length();i++) {...treść z poprzedniego slajdu... if(stos.size()>0) System.out.println("Błąd: Brak nawiasu zamykającego!"); Kolejka FIFO First In First Out Kolejka ma zawsze początek i koniec Wstawiamy elementy na koniec P bi l k Pobieramy elementy z początku Zawsze przechowywane wskaźnik na początek (pierwszy element w kolejce) wskaźnik na koniec (ostatnio dodany element) liczba elementów 5

Definicja klasy Kolejka (Queue) class Queue { int[ ] tablica; int nelem; int front; // początek kolejki int rear; // koniec kolejki public Queue(int wielkosc) { tablica = new int[wielkosc]; nelem = 0; front = 0; rear = -1; public void insert(int wartosc); public int remove(); front rear Obsługa kolejki public void insert(int wartosc) { rear++; // przesuń wskaźnik końca tablica[rear]=wartosc; // wstaw nowy element nelem++; // zwiększ długość kolejki public int remove() { int wartosc = tablica[front]; // zapamiętaj wartość z początku front++; // przesuń wskaźnik początku nelem--; // zmniejsz długość kolejki return wartosc; Dla kolejki cyklicznej jest to trochę trudniejsze Funkcja insert (wstaw) public void insert(int wartosc) { rear++; // przesuń wskaźnik if(rear == tablica.length) rear=0; // jeśli wskaźnik na końcu tablicy to przewiń tablica[rear]=wartosc; // wstaw nowy element nelem++; // zwiększ długość kolejki 6

Funkcja remove (usuń) public int remove() { int wartosc = tablica[front]; front++; // przesuń wskaźnik początku if(front == tablica.length) // jeśli na końcu to przewiń front = 0; nelem--; // zmniejsz długość kolejki return wartosc; Kolejka priorytetowa Elementy w kolejce są posortowane Funkcja remove() zawsze pobiera największy element (ten o najwyższym priorytecie) Funkcja insert() wstawia element w odpowiednie miejsce w kolejce (tak jak funkcja wstaw dla tablicy uporządkowanej) Zwykle implementuje się je strukturach innych niż tablice (np. w kopcach) Obliczanie wartości wyrażenia Dwa etapy: Konwersja wyrażenia arytmetycznego na notację ONP Obliczenie wartości wyrażenia w notacji ONP Obliczenie wartości wyrażenia w notacji ONP W obu przypadkach przyda się stos 7

Notacja ONP Odwrotna Notacja Polska (Reverse Polish Notation) Polski wkład w informatykę (Łukasiewicz) Notacja pozwala na zapis wyrażeń arytmetycznych bez użycia nawiasów Budowa notacji nawiasowej <argument> <operator> <argument> (np. a+b) Budowa notacji ONP <argument> <argument> <operator> (np. ab+ ) Konwersja wyrażeń na ONP a+b > ab+ a*b+c > ab*c+ a*(b+c) > abc+* a+b*c+d > abc*+d+ (a+b) * (c+d) > ab+cd+* a+b-c+d > ab+c-d+ a+(b-c)+d > abc-+d+ Co nam daje ONP? Uproszczenie zapisu (brak nawiasów) Możliwość analizy i obliczania wartości wyrażeń po kolei od lewej do prawej Algorytm obliczania wyrażenia: pobierz znak jeśli argument odłóż na stosie jeśli operator pobierz ze stosu dwa argumenty wykonaj działanie wstaw wynik na stos jeśli koniec wyrażenia zdejmij ze stosu wynik 8

Implementacja obliczenia for(int i=0;i<txt.length();i++) { char znak = txt.charat(i); if(znak>='0' && znak<='9') stos.push( (int)(znak-'0') ); // argumenty na stos else { // operator przelicz dwa ostatnie argumenty int arg2 = stos.pop(); // pobierz argumenty ze stosu int arg1 = stos.pop(); int wynik = 0; if(znak=='+') wynik = arg1 + arg2; // wykonaj działanie if(znak=='-') wynik = arg1 - arg2; if(znak=='*') wynik = arg1 * arg2; if(znak=='/') wynik = arg1 / arg2; stos.push(wynik); return stos.pop(); // na końcu na stosie jeden element - wynik Przykład 1 Notacja nawiasowa: 4*(8-2)/3+2 = 10 Notacja ONP: 482-*3/2+ Obliczenia: 482 4,8,2, 4,6, * 24,3,/ 8,2,+ 10 Uwaga: jeśli wyniki cząstkowe nie są całkowite będą zaokrąglane! Przykład 2 Notacja nawiasowa: (2+3)*(8+2)/5+7 = 17 Notacja ONP: 23+82+*5/7+ Obliczenia: 23 2,3,+ 5,8,2,+ 5,10,* 50,5,/ 10,7,+ 17 9

Zamiana wyrażenia na ONP Znowu używamy stosu! Tym razem wrzucamy do niego operatory a nie argumenty Algorytm: pobierz znak jeśli argument wypisz na wyjście jeśli nawias otwierający na stos jeśli nawias zamykający zdejmij ze stosu wszystko do nawiasu otwierającego i wypisz na wyjście jeśli operator zdejmij ze stosu i wypisz operatory o wyższym priorytecie aż do nawiasu otwierającego, umieść operator na stosie jeśli koniec wyrażenia wypisz zawartość stosu na wyjście Listy Dr inż. Paweł Kasprowski pawel@kasprowski.pl Listy a tablice Zalety: Nie trzeba z góry definiować wielkości listy Szybsze wstawianie w środek listy S b i Szybsze usuwanie Wady Wolniejsze wyszukiwanie Więcej miejsca w pamięci 10

Zasada działania Każdy element listy zawiera wskaźnik na kolejny Wystarczy, ze znamy wskaźnik na pierwszy element dane next dane next dane next Element listy class Element { int dana;... Element next; //adres następnego elementu Element listy class Element { public int dana;... public Element next; //adres następnego elementu public Element(int dana) { this.dana = dana; this.next = null; 11

Klasa Lista class Lista { Element head; public Lista() { head = null; public void wstaw(int klucz); public void usun(int klucz); public boolean szukaj(int klucz);... Klasa ArrayMain class ArrayMain { public static void main() { Array tab = new Array(20); for(int i=0; i<10; i++) { tab.wstaw(100*i + 2); tab.pokaztablice(); tab.wstaw(250); if(tab.szukaj(120)) System.out.println("Znaleziono "); Klasa ListaMain class ListaMain { public static void main() { Lista lista = new Lista(); for(int i=0; i<10; i++) { lista.wstaw(100*i + 2); lista.pokazliste(); lista.wstaw(250); if(lista.szukaj(120)) System.out.println("Znaleziono "); 12

Metoda wstawpierwszy() public void wstawpierwszy(int klucz) { Element x = new Element(klucz); x.next = head; head = x; Metoda pokazliste() public void pokazliste() { x = head; while(x!=null) { System.out.println("Element: "+x.dana); x = x.next; ListaMain.java Metoda wstaw() public void wstaw (int klucz) { Element elem = new Element(klucz); x = head; hil (! ll) { // jś i d i while(x.next!= null) { // przejście do ostatniego x = x.next; // tutaj x wskazuje na ostatni element x.next = elem; 13

Metoda usunpierwszy() public void usunpierwszy() { head = head.next; Uwaga1: W Javie nie trzeba zwalniać pamięci! Uwaga2: Jeśli nie ma na liście elementów to head=null i metoda wygeneruje wyjątek NullPointerException! Metoda usunpierwszy() public void usunpierwszy() { if(head!= null) head = head.next; Zwracanie usuniętego elementu public Element usunpierwszy() { Element x = head; if(head!= null) h d h d head = head.next; return x; 14

Zwracanie wartości usuniętego elementu public int usunpierwszy() { int x = head.dana; if(head!= null) head = head.next; return x; Uwaga! Znowu może być NullPointerException Zwracanie wartości usuniętego elementu public int usunpierwszy() { int x = -1; if(head!= null) { x = head.dana; d head = head.next; return x; Metoda usun() dla tablicy public void usun(int klucz) { int i=0; while(i<nelem && tablica[i]!= klucz) // wyszukanie i i 1 i = i + 1; while(i<=nelem-1) { // przesunięcie tablica[i] = tablica[i+1]; i++; 15

Metoda usun() dla listy public void usun(int klucz) { Element x = head; while(x!=null && x.dana!= klucz) // wyszukanie x = x.next;... Metoda usun() dla listy public void usun(int klucz) { Element x = head; Element xprev = null; while(x!=null && x.dana!= klucz) { // wyszukanie xprev = x; x = x.next; // tutaj: // x - element do usunięcia, // xprev - element poprzedni Metoda usun() dla listy public void usun(int klucz) { Element x = head; Element xprev = null; while(x!=null && x.dana!= klucz) { // wyszukanie xprev = x; x = x.next; if(x!=null) { // usunięcie elementu z łańcucha xprev.next = x.next; 16

Metoda usun() dla listy public void usun(int klucz) { Element x = head; Element xprev = null; while(x!=null && x.dana!= klucz) { // wyszukanie xprev = x; x = x.next; if(x!=null) { // usunięcie elementu z łańcucha xprev.next = x.next; Problem: co jeśli usuwamy pierwszy element? Metoda usun() dla listy public void usun(int klucz) { Element x = head; Element xprev = null; while(x!=null && x.dana!= klucz) { // wyszukanie xprev = x; x = x.next; if(x!=null) { // usunięcie elementu z łańcucha if(xprev!= null) xprev.next = x.next; else // usuwamy pierwszy element head = x.next; Zwracanie usuwanego elementu public Element usun2(int klucz) { Element x = head; Element xprev = null; while(x!=null && x.dana!= klucz) { // wyszukanie xprev = x; x = x.next; if(x!=null) { // usunięcie elementu z łańcucha if(xprev!= null) xprev.next = x.next; else head = x.next; return x; 17

Zwracanie wartości usuwanego elementu public int usun2(int klucz) { Element x = head; Element xprev = null; while(x!=null && x.dana!= klucz) { // wyszukanie xprev = x; x = x.next; if(x!=null) { // usunięcie elementu z łańcucha if(xprev!= null) xprev.next = x.next; else head = x.next; return (x!=null)?x.dana:-1; Implementacja stosu Metoda push() wstawienie nowego elementu na szczyt stosu po prostu metoda wstawpierwszy() Metoda pop() usunięcie elementu ze szczytu stosu po prostu metoda usunpierwszy() Z punktu widzenia użytkownika stosu sposób przechowywania danych (tablica czy lista) jest obojętny on używa tylko metod push() i pop() Implementacja kolejki Metoda insert() wstawia element na koniec kolejki po prostu metoda wstaw() Metoda remove() pobiera pierwszy element z kolejki po prostu metoda usunpierwszy() Lista jest tworzona dynamicznie nie ma tu potrzeby "zawijania" jak przy użyciu tablicy 18

Kolejka tablica czy lista? Tablica konieczność określenia maksymalnej wielkości stosu/kolejki czas usuwania rzędu O(n) czas wstawiania rzędu O(1) gdy na koniec! Lista większy rozmiar danych (przechowywanie linków) czas usuwania rzędu O(1) czas wstawiania rzędu O(n) konieczność przejścia na koniec listy Ale to można poprawić! Przechowanie końca listy class Lista { Element head; Element tail; public Lista() { head = null; tail = null;... Szybsze wstaw() public void wstaw (int klucz) { Element elem = new Element(klucz); tail.next = elem; tail = elem; 19

Poprawka w usunpierwszy() public int usunpierwszy() { int x = -1; if(head!= null) { x = head.dana; d head = head.next; if(head==null) tail=null; return x; Listy dwukierunkowe Oprócz next, także prev Możliwość przechodzenia w obie strony listy Usuwanie i wstawianie robi się bardziej skomplikowane Wyszukiwanie może być łatwiejsze Dziękuję za uwagę Do zobaczenia... materiały dostępne pod adresem: www.kasprowski.pl 20