Spojové struktury. Jan Faigl. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze. Přednáška 10 A0B36PR1 Programování 1

Podobné dokumenty
Část I Spojové struktury

Spojové struktury. Jan Faigl. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze

Dynamické struktury a Abstraktní Datový Typy (ADT)

Část 1 Spojové struktury (stromy) Dynamické struktury a Abstraktní Datový Typy (ADT) Část 2 Abstraktní datový typ. Část 3 Příklad ADT Prioritní fronta

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

Kolekce, cyklus foreach

Abstraktní datové typy

Spojová implementace lineárních datových struktur

Dynamické datové struktury I.

Fronta (Queue) Úvod do programování. Fronta implementace. Fronta implementace pomocí pole 1/4. Fronta implementace pomocí pole 3/4

Základní datové struktury

ADT/ADS = abstraktní datové typy / struktury

typová konverze typová inference

Datové struktury. alg12 1

Dynamické datové struktury IV.

Abstraktní datové typy: zásobník

Úvod do programovacích jazyků (Java)

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Výčtový typ strana 67

Lineární datové struktury

DSA, První krok: máme dokázat, že pro left = right vrátí volání f(array, elem, left, right)

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

Datové struktury. Obsah přednášky: Definice pojmů. Abstraktní datové typy a jejich implementace. Algoritmizace (Y36ALG), Šumperk - 12.

Konstruktory a destruktory

Stromy. Příklady. Rekurzivní datové struktury. Základní pojmy

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Šablony, kontejnery a iterátory

Generické programování

Šablony, kontejnery a iterátory

8 Třídy, objekty, metody, předávání argumentů metod

Programování v C++, 2. cvičení

Programování v C++ 2, 4. cvičení

Spojový seznam. Jan Kybic.

součet cvičení celkem. známka. Úloha č.: max. bodů: skut. bodů:

Programování v C++ 2, 8. cvičení

Příklad : String txt1 = new String( Ahoj vsichni! ); //vytvoří instanci třídy String a přiřadí ji vnitřní hodnotu Ahoj vsichni!

Příklad aplikace Klient/Server s Boss/Worker modelem (informativní)

Datové typy v Javě. Tomáš Pitner, upravil Marek Šabo

Programování v C++ 1, 5. cvičení

Teoretické minimum z PJV

9. přednáška - třídy, objekty

ABSTRAKTNÍ DATOVÉ TYPY

Základní pojmy. Úvod do programování. Základní pojmy. Zápis algoritmu. Výraz. Základní pojmy

Algoritmizace prostorových úloh

Programování v C++ 2, 7. cvičení

Lineární spojový seznam (úvod do dynamických datových struktur)

boolean hasnext() Object next() void remove() Kolekce

Algoritmizace prostorových úloh

Úvod Přetěžování Generika Kolekce Konec. Programování v C# Další jazykové konstrukce. Petr Vaněček 1 / 31

Platforma Java. Petr Krajča. Katedra informatiky Univerzita Palackého v Olomouci. Petr Krajča (UP) KMI/PJA: Seminář V. 27. říjen, / 15

Algoritmizace a programování

Datové struktury obsah přednášky 1. Úvod 2. Třídy Type-wrapper (obalový typ) pro primitivní typy automatické převody 3. Automatické převody mezi

Algoritmy a datové struktury

IRAE 07/08 Přednáška č. 7. Začátek (head)

7. Dynamické datové struktury

20. Projekt Domácí mediotéka

Abstraktní datový typ

Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39

Vytváření a použití knihoven tříd

Programování v C++ 3, 3. cvičení

5 Rekurze a zásobník. Rekurzivní volání metody

PŘETĚŽOVÁNÍ OPERÁTORŮ

Abstraktní datový typ

Část I. Část 1 Abstraktní datový typ. Přehled témat. Abstraktní datový typ. Zdroje

10 Generické implementace

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Neměnné objekty. Tomáš Pitner, upravil Marek Šabo

Dynamické datové struktury III.

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

V případě jazyka Java bychom abstraktní datový typ Time reprezentující čas mohli definovat pomocí třídy takto:

ÚVODNÍ ZNALOSTI. datové struktury. správnost programů. analýza algoritmů

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Cílem kapitoly je seznámit studenta se seznamem a stromem. Jejich konstrukci, užití a základní vlastnosti.

Algoritmy I, složitost

Da D to t v o é v ty t py IB111: Datové typy

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

1. D Y N A M I C K É DAT O V É STRUKTUR Y

Čipové karty Lekařská informatika

SPJA, cvičení 1. ipython, python, skripty. základy syntaxe: základní datové typy, řetězce. podmínky: if-elif-else, vyhodnocení logických výrazů

Java - řazení objektů

Úvod do programování - Java. Cvičení č.4

Jazyk C# (seminář 3)

Algoritmizace a programování

Základy algoritmizace. Hašování

Jazyk C# (seminář 6)

ALG 04. Zásobník Fronta Operace Enqueue, Dequeue, Front, Empty... Cyklická implementace fronty. Průchod stromem do šířky

Iterator & for cyklus

Abstraktní datové typy FRONTA

Část 1 Abstraktní datový typ. Datové struktury a abstraktní datový typ

Programování v Javě I. Leden 2008

Programování v C++ 1, 16. cvičení

ABSTRAKTNÍ DATOVÉ TYPY (ADT)

2 Datové struktury. Pole Seznam Zásobník Fronty FIFO Haldy a prioritní fronty Stromy Hash tabulky Slovníky

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

5. Vyhledávání a řazení 1

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

Generické typy. Podrobněji: The Java Language Specification ( Third Edition ) , 18

Amortizovaná složitost. Prioritní fronty, haldy (binární, d- regulární, binomiální, Fibonacciho), operace nad nimi a jejich složitost

Transkript:

Spojové struktury Jan Faigl Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Přednáška 10 A0B36PR1 Programování 1 Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 1 / 54

Část 1 Spojové struktury (seznamy) Spojové struktury Spojový seznam Spojový seznam s odkazem na konec seznamu Příklad použití Vložení/odebrání prvku Kruhový spojový seznam Obousměrný seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 2 / 54

Část I Spojové struktury Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 3 / 54

Obsah Spojové struktury Spojový seznam Spojový seznam s odkazem na konec seznamu Příklad použití Vložení/odebrání prvku Kruhový spojový seznam Obousměrný seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 4 / 54

Kolekce prvků (položek) V programech je velmi běžný požadavek na uchování seznamu (množiny) prvků (proměnných/objektů) Viz příklad geometrických objektů v 8. a 9. přednášce Základní příkladem je pole (statické délky) V Javě definováno jménem typu a [], například double[] Jedná se o kolekci položek (proměnných) stejného typu + Umožňuje jednoduchý přístup k položkám indexací prvku Položky jsou stejného typu (velikosti) Velikost pole je určena při vytvoření pole Operátor new Velikost (maximální velikost) musí být známa v době vytváření Změna velikost v podstatě není přímo možná Nutné nové vytvoření (alokace paměti) Využití pouze malé části pole je mrháním paměti V případě řazení pole přesouváme položky Vložení prvku a především mazání prvku vyžaduje kopírování položek Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 5 / 54

Seznam list Seznam (proměnných nebo objektů) patří mezi základní datové struktury Základní ADT Abstract Data Type Seznam zpravidla nabízí sadu základních operací: Vložení prvku (insert) Odebrání prvku (remove) Vyhledání prvku Aktuální počet prvku v seznamu Implementace seznamu může být různá: Pole statické délky Indexování je velmi rychlé Vložení prvků může být pomalé (nová alokace a kopírování) Viz například GeomObjectArray z 9. přednášky. lec09/geomobjectarray.java Spojové seznamy Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 6 / 54

Seznam list Seznam (proměnných nebo objektů) patří mezi základní datové struktury Základní ADT Abstract Data Type Seznam zpravidla nabízí sadu základních operací: Vložení prvku (insert) Odebrání prvku (remove) Vyhledání prvku Aktuální počet prvku v seznamu Implementace seznamu může být různá: Pole statické délky Indexování je velmi rychlé Vložení prvků může být pomalé (nová alokace a kopírování) Viz například GeomObjectArray z 9. přednášky. lec09/geomobjectarray.java Spojové seznamy Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 6 / 54

Spojové seznamy Datová struktura realizující seznam variabilní délky Každý prvek seznamu obsahuje Datovou část (hodnota proměnné / objekt) Referenci na další prvek v seznamu null v případě posledního prvku seznamu. První prvek seznamu se zpravidla označuje jako head nebo start Realizujeme jej jako referenční proměnnou odkazující na první prvek seznamu Data Next null Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 7 / 54

Spojové seznamy Datová struktura realizující seznam variabilní délky Každý prvek seznamu obsahuje Datovou část (hodnota proměnné / objekt) Referenci na další prvek v seznamu null v případě posledního prvku seznamu. První prvek seznamu se zpravidla označuje jako head nebo start Realizujeme jej jako referenční proměnnou odkazující na první prvek seznamu start Data Next null Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 7 / 54

Základní operace se spojovým seznamem Vložení prvku Předchozí prvek odkazuje na nový prvek Nový prvek může odkazovat na předchozí prvek, který na něj odkazuje Tzv. obousměrný spojový seznam Odebrání prvku Předchozí prvek aktualizuje hodnotu odkazu na následující prvek Předchozí prvek tak nově odkazuje na následující hodnotu, na kterou odkazoval odebíraný prvek Základní implementací spojového seznamu je tzv. jednosměrný spojový seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 8 / 54

Základní operace se spojovým seznamem Vložení prvku Předchozí prvek odkazuje na nový prvek Nový prvek může odkazovat na předchozí prvek, který na něj odkazuje Tzv. obousměrný spojový seznam Odebrání prvku Předchozí prvek aktualizuje hodnotu odkazu na následující prvek Předchozí prvek tak nově odkazuje na následující hodnotu, na kterou odkazoval odebíraný prvek Základní implementací spojového seznamu je tzv. jednosměrný spojový seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 8 / 54

Jednosměrný spojový seznam Příklad spojového seznamu pro uložení číselných hodnot 17 93 79 Přidání prvku 50 na konec seznamu 17 93 79 50 Odebrání prvku 79 17 93 50 1. Nejdříve sekvenčně najdeme prvek s hodnotou 79 2. Následně vyjmeme a napojíme prvek 93 na prvek 50 Hodnotu reference next prvku 93 nastavíme na hodnotu reference next odebíraného prvku, tj. na prvek 50 Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 9 / 54

Jednosměrný spojový seznam Příklad spojového seznamu pro uložení číselných hodnot 17 93 79 Přidání prvku 50 na konec seznamu 17 93 79 50 Odebrání prvku 79 17 93 50 1. Nejdříve sekvenčně najdeme prvek s hodnotou 79 2. Následně vyjmeme a napojíme prvek 93 na prvek 50 Hodnotu reference next prvku 93 nastavíme na hodnotu reference next odebíraného prvku, tj. na prvek 50 Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 9 / 54

Jednosměrný spojový seznam Příklad spojového seznamu pro uložení číselných hodnot 17 93 79 Přidání prvku 50 na konec seznamu 17 93 79 50 Odebrání prvku 79 17 93 50 1. Nejdříve sekvenčně najdeme prvek s hodnotou 79 2. Následně vyjmeme a napojíme prvek 93 na prvek 50 Hodnotu reference next prvku 93 nastavíme na hodnotu reference next odebíraného prvku, tj. na prvek 50 Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 9 / 54

Obsah Spojové struktury Spojový seznam Spojový seznam s odkazem na konec seznamu Příklad použití Vložení/odebrání prvku Kruhový spojový seznam Obousměrný seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 10 / 54

Spojový seznam v Javě Seznam tvoří dvě třídy Zapouzdření vlastního listu Třída pro uložení prvku seznamu Vlastní data prvku Odkaz (reference) na další prvek Příklad tříd pro uložení spojového seznamu celých čísel class ListNode { int value; ListNode next; public class LinkedList { ListNode start;... Pro jednoduchost prvky seznamu obsahují celé číslo. Obecně mohou obsahovat libovolný objekt (referenci na objekt). Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 11 / 54

Zobecnění pro uložení objektů V Javě jsou všechny typy (kromě primitivních typů) odvozeny od třídy Object Můžeme tak zobecnit spojový seznam pro uložení libovolných objektů class ListNode { Object item; ListNode next; public class LinkedList { ListNode start;... Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 12 / 54

Příklad LinkedList Prvky zapouzdříme uvnitř třídy LinkedList public class LinkedList { class ListNode { //inner class Object item; ListNode next; ListNode(Object item) { this.item = item; next = null; private ListNode start; public LinkedList() { start = null; Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 13 / 54

LinkedList push Přidání prvku na začátek public void push(object obj) { ListNode node = new ListNode(obj); if (start == null) { // 1st element start = node; else { node.next = start; // update the reference start = node; // set new start Přidání prvku není závislé na počtu prvků v seznamu Konstantní složitost operace push O(1) Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 14 / 54

LinkedList pop Odebrání prvního prvku ze seznamu public Object pop() { Object ret = null; if (start!= null) { ret = start.item; start = start.next; //can be next item or null return ret; Odebrání prvku není závislé na počtu prvků v seznamu Konstantní složitost operace pop O(1) Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 15 / 54

LinkedList pop Odebrání prvního prvku ze seznamu public Object pop() { Object ret = null; if (start!= null) { ret = start.item; start = start.next; //can be next item or null return ret; Odebrání prvku není závislé na počtu prvků v seznamu Konstantní složitost operace pop O(1) Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 15 / 54

LinkedList size Zjištění počtu prvků v seznamu vyžaduje projít seznam až k zarážce null, tj. položka next objektu typu ListNode je null public int size() { int count = 0; ListNode cur = start; while(cur!= null) { cur = cur.next; count++; return count; Pro zjištění počtu prvků v seznamu musíme projít kompletní seznam, tj. n položek Lineární složitost operace size O(n) Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 16 / 54

LinkedList size Zjištění počtu prvků v seznamu vyžaduje projít seznam až k zarážce null, tj. položka next objektu typu ListNode je null public int size() { int count = 0; ListNode cur = start; while(cur!= null) { cur = cur.next; count++; return count; Pro zjištění počtu prvků v seznamu musíme projít kompletní seznam, tj. n položek Lineární složitost operace size O(n) Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 16 / 54

LinkedList back Vrácení hodnoty posledního prvku ze seznamu public Object back() { ListNode end = start; while(end!= null && end.next!= null) { end = end.next; return end == null? null : end.item; Pro vrácení hodnoty posledního prvku v seznamu musíme projít všechny položky seznamu Lineární složitost operace back O(n) Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 17 / 54

LinkedList back Vrácení hodnoty posledního prvku ze seznamu public Object back() { ListNode end = start; while(end!= null && end.next!= null) { end = end.next; return end == null? null : end.item; Pro vrácení hodnoty posledního prvku v seznamu musíme projít všechny položky seznamu Lineární složitost operace back O(n) Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 17 / 54

Obsah Spojové struktury Spojový seznam Spojový seznam s odkazem na konec seznamu Příklad použití Vložení/odebrání prvku Kruhový spojový seznam Obousměrný seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 18 / 54

LinkedList zrychlení operací size and back Operace size a back procházejí kompletní seznam Operaci size můžeme urychlit pokud budeme udržovat aktuální počet položek v seznamu Zavedeme datovou položku int count Počet prvků inkrementujeme při každém přidání prvku a dekrementuje při každém odebrání prvku Operaci back můžeme urychlit referenční proměnou odkazující na poslední prvek public class LinkedList {... private ListNode end;... V případě přidání prvku na začátek, aktualizujeme pouze pokud byl seznam doposud prázdný Aktualizujeme v případě přidání prvku na konec Nebo při vyjmutí posledního prvku Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 19 / 54

LinkedList zrychlení operací size and back Operace size a back procházejí kompletní seznam Operaci size můžeme urychlit pokud budeme udržovat aktuální počet položek v seznamu Zavedeme datovou položku int count Počet prvků inkrementujeme při každém přidání prvku a dekrementuje při každém odebrání prvku Operaci back můžeme urychlit referenční proměnou odkazující na poslední prvek public class LinkedList {... private ListNode end;... V případě přidání prvku na začátek, aktualizujeme pouze pokud byl seznam doposud prázdný Aktualizujeme v případě přidání prvku na konec Nebo při vyjmutí posledního prvku Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 19 / 54

LinkedList urychlený size public class LinkedList { private int count; public LinkedList() {... count = 0; public int size() { return count; public void push(object obj) { ListNode node = new ListNode(obj); count++;... public Object pop() { Object ret = null; if (start!= null) { count--;... return ret; Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 20 / 54

LinkedList push s odkazem na konec seznamu public void push(object obj) { ListNode node = new ListNode(obj); if (start == null) { start = node; end = start; //update tail reference else { node.next = start; start = node; Hodnotu referenční proměnné end nastavujeme pouze pokud byl seznam prázdný, protože prvky přidáváme na začátek. Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 21 / 54

LinkedList pop s odkazem na konec seznamu public Object pop() { Object ret = null; if (start!= null) { ret = start.item; start = start.next; if (start == null) { end = null; // update the tail reference return ret; Hodnotu referenční proměnné end nastavujeme pouze pokud byl odebrán poslední prvek, protože prvky odebíráme ze začátku. Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 22 / 54

LinkedList back s odkazem na konec seznamu Proměnná end je buď null nebo odkazuje na poslední prvek seznamu public Object back() { return end!= null? end.item : null; Udržováním hodnoty proměnné end jsme snížili časovou náročnost operace back z lineární složitosti na počtu prvků v seznamu O(n) na konstantní složitost O(1) Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 23 / 54

Přidání prvku na konec seznamu LinkedList pushend public void pushend(object obj) { ListNode node = new ListNode(obj); if (end == null) { // adding the 1st element start = end = node; //update both start and end else { end.next = node; // update next of the previous end end = node; // set new end Na asymptotické složitost metody přidání dalšího prvku (na konec seznamu) se nic nemění, je nezávislé na aktuálním počtu prvků v seznamu Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 24 / 54

LinkedList popend Odebrání prvku z konce seznamu public Object popend() { if (start == null) { return null; Object ret = end.item; if (start == end) { // the last item is start = end = null; // removed from the list else { // there is also penultimate item ListNode cur = start; // that needs to be while(cur.next!= end) { // updated (its cur = cur.next; // reference to the // the next item) end = cur; // the penultimate is the new end end.next = null; // the end does not have next return ret; Složitost je O(n), protože musíme aktualizovat předposlední prvek. Alternativně lze řešit přes obousměrný spojový seznam. Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 25 / 54

Obsah Spojové struktury Spojový seznam Spojový seznam s odkazem na konec seznamu Příklad použití Vložení/odebrání prvku Kruhový spojový seznam Obousměrný seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 26 / 54

Výpis položek seznamu print Seznam postupně procházíme Seznam je obecný a pro tisk se využívá metody tostring public void print() { ListNode cur = start; while(cur!= null) { System.out.print( cur.item + (cur.next == null? "\n" : " ") ); cur = cur.next; lec10/linkedlistend.java Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 27 / 54

Příklad seznam celých čísel Integer Příklad použití na seznam objektu třídy Integer LinkedListEnd lst = new LinkedListEnd(); lst.push(10).push(5).pushend(17).push(7).pushend(21); lst.print(); System.out.println("Pop 1st item: " + lst.pop()); System.out.print("Lst: "); lst.print(); System.out.println("Back of the list: " + lst.back()); System.out.println("Pop from the end: " + lst.popend()); System.out.print("Lst: "); lst.print(); Výstup programu java DemoIntLinkedList 7 5 10 17 21 Pop 1st item: 7 Lst: 5 10 17 21 Back of the list: 21 Pop from the end: 21 Lst: 5 10 17 lec10/demointlinkedlist.java Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 28 / 54

Obsah Spojové struktury Spojový seznam Spojový seznam s odkazem na konec seznamu Příklad použití Vložení/odebrání prvku Kruhový spojový seznam Obousměrný seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 29 / 54

LinkedList vložení prvku do seznamu Vložení do seznamu: na začátek modifikujeme referenční proměnnou start (metoda push) na konec modifikujeme referenční proměnnou předposledního prvku a nastavujeme nový konec (metoda pushend) obecně potřebujeme hodnotu referenční proměnné prvku, za který chceme nový prvek vložit (node) ListNode newnode = new ListNode(obj); newnode.next = node.next; node.next = newnode; Do seznamu můžeme chtít prvek vložit na příslušné pořadí, tj. podle indexu v seznamu Případně můžeme také požadovat vložení podle hodnoty prvku, tj. vložit před prvek s příslušnou hodnotu. Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 30 / 54

LinkedList vložení prvku do seznamu Vložení do seznamu: na začátek modifikujeme referenční proměnnou start (metoda push) na konec modifikujeme referenční proměnnou předposledního prvku a nastavujeme nový konec (metoda pushend) obecně potřebujeme hodnotu referenční proměnné prvku, za který chceme nový prvek vložit (node) ListNode newnode = new ListNode(obj); newnode.next = node.next; node.next = newnode; Do seznamu můžeme chtít prvek vložit na příslušné pořadí, tj. podle indexu v seznamu Případně můžeme také požadovat vložení podle hodnoty prvku, tj. vložit před prvek s příslušnou hodnotu. Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 30 / 54

LinkedList insertat Vložení nového prvku na pozici index v seznamu public void insertat(object obj, int index) { if (index < 0) { return; //only positive position ListNode newnode = new ListNode(obj); ListNode node = getnode(index - 1); if (node == start) { // the replacement node can start = newnode; // be the start node if (node!= null) { // node can be null for the 1st node, i.e., the situation start == node == null newnode.next = node.next; node.next = newnode; Neřeší aktualizaci end (odkaz na konec seznamu) Pro napojení spojového seznamu potřebuje položku next, proto hledáme prvek na pozici index 1 Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 31 / 54

LinkedList getnode Nalezení prvku na pozici index Pokud je index vyšší než počet prvků v poli, návrat posledního prvku private ListNode getnode(int index) { ListNode cur = start; int i = 0; while(i < index && cur!= null && cur.next!= null) { cur = cur.next; i++; return cur; Pokud je seznam prázdný vrátí null. Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 32 / 54

Příklad vložení prvků do seznamu (LinkedList) Příklad vložení do seznam čísel Integer LinkedList lst = new LinkedList(); lst.push(10).push(5).push(17).push(7).push(21); lst.print(); lst.insertat(55, 2); lst.print(); lst.insertat(0, 0); lst.print(); lst.insertat(100, 10); lst.print(); Výstup programu java DemoInsertAt 21 7 17 5 10 21 7 55 17 5 10 0 7 55 17 5 10 0 7 55 17 5 10 100 lec10/demoinsertat.java Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 33 / 54

LinkedList getat(int index) Nalezení prvků v seznamu podle pozice v seznamu V případě adresace mimo rozsah seznamu vrátí null public Object getat(int index) { if (index < 0 start == null) { return null; ListNode cur = start; int i = 0; while(i < index && cur!= null && cur.next!= null) { cur = cur.next; i++; return (cur!= null && i == index)? cur.item : null; Složitost operace je v nejnepříznivějším případě O(n) (v případě pole je to O(1)) Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 34 / 54

Příklad použití getat(int index) Příklad vypsání obsahu seznamu metodou getat v cyklu LinkedList lst = new LinkedList(); lst.push(10).push(5).push(17).push(7).push(21); lst.print(); for(int i = 0; i < 7; ++i) { System.out.println("lst[" + i + "]: " + lst.getat(i)); Výstup programu javac DemoGetAt.java && java DemoGetAt 21 7 17 5 10 lst[0]: 21 lst[1]: 7 lst[2]: 17 lst[3]: 5 lst[4]: 10 lst[5]: null lst[6]: null lec10/demogetat.java V tomto případě v každém běhu cyklu je složitost metody get O(n) a tedy výpis obsahu seznamu má složitost O(n 2 )! Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 35 / 54

LinkedList removeat(int index) Odebrání prvku na pozici int index a navážeme seznam Pro navázání seznamu potřebujeme prvek na pozici index 1 public void removeat(int index) { if (index < 0 start == null) { return; if (index == 0) { pop(); //call the pop function to handle start else { ListNode node = getnode(index - 1); if (node.next!= null) { node.next = node.next.next; Složitost v nejnepříznivější případě O(n) (nejdříve musíme najít prvek). Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 36 / 54

Příklad použití removeat(int index) LinkedList lst = new LinkedList(); lst.push(10).push(5).push(17).push(7).push(21); lst.print(); System.out.println("Remove item at 3 (" + lst.getat(3) + ")"); lst.removeat(3); lst.print(); System.out.println("Remove item at 3 (" + lst.getat(3) + ")"); lst.removeat(3); lst.print(); System.out.println("Remove item at 0 (" + lst.getat(0) + ")"); lst.removeat(0); lst.print(); Výstup programu javac DemoRemoveAt.java && java DemoRemoveAt 21 7 17 5 10 Remove item at 3 (5) 21 7 17 10 Remove item at 3 (10) 21 7 17 Remove item at 0 (21) 7 17 lec10/demoremoveat.java Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 37 / 54

Vyhledání prvku v seznamu podle obsahu indexof Vrátí číslo pozice prvního výskytu prvku v seznamu Pokud není prvek v seznamu nalezen vrátí -1 public int indexof(object obj) { int count = 0; ListNode cur = start; boolean found = false; while(cur!= null &&!found) { found = cur.item.equals(obj); cur = cur.next; count++; return found? count-1 : -1; Porovnání hodnot objektů metodou equals! Porovnání operátorem == porovná hodnoty referenčních proměnných (adresy), nikoliv obsah. Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 38 / 54

Příklad použití indexof 1/3 LinkedList lst = new LinkedList(); lst.push(10).push(5).push(17).push(7).push(21); lst.print(); Integer i = 5; System.out.println("Index of (" + i + ") is " + lst.indexof(i)); i = i + 12; System.out.println("Index of (" + i + ") is " + lst.indexof(i)); i = 3; System.out.println("Index of (" + i + ") is " + lst.indexof(i)); Výstup programu java DemoIndexOfInt 21 7 17 5 10 Index of (5) is 3 Index of (17) is 2 Index of (3) is -1 lec10/demoindexofint.java Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 39 / 54

Příklad použití indexof 2/3 LinkedList lst = new LinkedList(); lst.push("fee").push("ctu").push("pr1").push("lecture10"); lst.print(); String s = "PR1"; System.out.println("Index of (" + s + ") is " + lst.indexof(s)); s = "Fee"; System.out.println("Index of (" + s + ") is " + lst.indexof(s)); Výstup programu javac DemoIndexOfString.java && java DemoIndexOfString Lecture10 PR1 CTU FEE Index of (PR1) is 1 Index of (Fee) is -1 lec10/demoindexofstring.java Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 40 / 54

Příklad použití indexof 3/3 LinkedList lst = new LinkedList(); lst.push(10).push(5).push("fee").push(7).push("ctu"); lst.print(); Integer i = 5; System.out.println("Index of (" + i + ") is " + lst.indexof(i)); String s = "FEE"; System.out.println("Index of (" + s + ") is " + lst.indexof(s)); Výstup programu javac DemoIndexOfMix.java && java DemoIndexOfMix CTU 7 FEE 5 10 Index of (5) is 3 Index of (FEE) is 2 Využití objektového přístup, dědičnosti a polymorfismu lec10/demoindexofmix.java Se zavedením generických typů, je i v Javě kladen důraz na statickou typovou kontrolu, tj. kontrolu typů při překladu. Jsou upřednostňovány parametrizované datové struktur pro konkrétní typy (např. Integer nebo String). Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 41 / 54

Příklad použití indexof 3/3 LinkedList lst = new LinkedList(); lst.push(10).push(5).push("fee").push(7).push("ctu"); lst.print(); Integer i = 5; System.out.println("Index of (" + i + ") is " + lst.indexof(i)); String s = "FEE"; System.out.println("Index of (" + s + ") is " + lst.indexof(s)); Výstup programu javac DemoIndexOfMix.java && java DemoIndexOfMix CTU 7 FEE 5 10 Index of (5) is 3 Index of (FEE) is 2 Využití objektového přístup, dědičnosti a polymorfismu lec10/demoindexofmix.java Se zavedením generických typů, je i v Javě kladen důraz na statickou typovou kontrolu, tj. kontrolu typů při překladu. Jsou upřednostňovány parametrizované datové struktur pro konkrétní typy (např. Integer nebo String). Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 41 / 54

Odebrání prvku ze seznam podle jeho obsah Podobně jako vyhledání prvku podle obsahu můžeme prvky odebrat Můžeme implementovat přímo nebo s využitím již existujících metod indexof a removeat Příklad implementace public void remove(object obj) { int idx = indexof(obj); while(idx!= -1) { removeat(idx); idx = indexof(obj); Odebíráme všechny výskyty objektu v seznamu. Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 42 / 54

Odebrání prvku ze seznam podle jeho obsah Podobně jako vyhledání prvku podle obsahu můžeme prvky odebrat Můžeme implementovat přímo nebo s využitím již existujících metod indexof a removeat Příklad implementace public void remove(object obj) { int idx = indexof(obj); while(idx!= -1) { removeat(idx); idx = indexof(obj); Odebíráme všechny výskyty objektu v seznamu. Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 42 / 54

Obsah Spojové struktury Spojový seznam Spojový seznam s odkazem na konec seznamu Příklad použití Vložení/odebrání prvku Kruhový spojový seznam Obousměrný seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 43 / 54

Kruhový spojový seznam Položka next posledního prvku může odkazovat na první prvek Tak vznikne kruhový spojový seznam 17 93 79 50 Při přidání prvku na začátek je nutné aktualizovat hodnotu položky next posledního prvku Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 44 / 54

Obsah Spojové struktury Spojový seznam Spojový seznam s odkazem na konec seznamu Příklad použití Vložení/odebrání prvku Kruhový spojový seznam Obousměrný seznam Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 45 / 54

Obousměrný spojový seznam Každý prvek obsahuje odkaz na následující a předchozí položku v seznamu, položky prev a next První prvek má nastavenu položku prev na hodnotu null Poslední prvek má next nastavenu na null Příklad obousměrného seznamu celých čísel 17 93 79 Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 46 / 54

Příklad DoubleLinkedList public class DoubleLinkedList { class ListNode { //inner class ListNode prev; ListNode next; Object item; ListNode(Object item) { this.item = item; prev = null; next = null; private ListNode start; public LinkedList() { start = null; Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 47 / 54

DoubleLinkedList vložení prvku Vložení prvku před prvek cur: 1. Napojení vloženého prvku do seznamu, hodnoty prev a next 2. Aktualizace next předchozí prvku k prvku cur 3. Aktualizace prev proměnné prvku cur public void insert(object obj, ListNode cur) { ListNode newnode = new ListNode(obj); newnode.next = cur; newnode.prev = cur.prev; if (cur.prev!= null) { cur.prev.next = newnode; cur.prev = newnode; Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 48 / 54

DoubleLinkedList přidání prvku na začátek seznamu push public DoubleLinkedList push(object obj) { ListNode node = new ListNode(obj); if (start == null) { start = end = node; else { node.next = start; start.prev = node; start = node; return this; lec10/doublelinkedlist.java Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 49 / 54

DoubleLinkedList tisk seznamu print a printreverse public void print() { ListNode cur = start; while(cur!= null) { System.out.print(cur.item + (cur.next == null? "\n" : " ")); cur = cur.next; public void printreverse() { ListNode cur = end; while(cur!= null) { System.out.print(cur.item + (cur.prev == null? "\n" : " ")); cur = cur.prev; Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 50 / 54

Příklad použití DoubleLinkedList lst = new DoubleLinkedList(); lst.push("a").push("bb").push("ccc").push("dddd"); System.out.println("Regular print: "); lst.print(); System.out.println("Revert print: "); lst.printreverse(); Výstup programu javac DemoDoubleLinkedList.java && java DemoDoubleLinkedList Regular print: DDDD CCC BB A Revert print: A BB CCC DDDD lec10/demodoublelinkedlist.java Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 51 / 54

Kruhový obousměrný seznam Položka next posledního prvku odkazuje na první prvek Položka prev prvního prvku odkazuje na poslední prvek 17 93 79 50 Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 52 / 54

Diskutovaná témata Shrnutí přednášky Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 53 / 54

Diskutovaná témata Diskutovaná témata Spojové seznamy lineární spojové struktury Jednosměrný spojový seznam Operace vkládání a odebrání prvku Průchod seznamem Vyhledávání prvku v seznamu Kruhový jednosměrný spojový seznam Obousměrný spojový seznam Kruhový obousměrný spojový seznam Příště: Nelineární spojové struktury a abstraktní datový typ Jan Faigl, 2015 A0B36PR1 Přednáška 10: Spojové struktury 54 / 54