Spojový seznam. Jan Kybic.

Podobné dokumenty
Prioritní fronta, halda

Třídění a vyhledávání Searching and sorting

Stromy. Jan Kybic.

Záznam, zásobník a fronta

Rekurze a rychlé třídění

6. Abstraktní datové typy

Rozptylovací tabulky

Kolekce, cyklus foreach

Abstraktní datové typy

IB111 Úvod do programování skrze Python

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

Dynamické datové struktury III.

Dynamické datové struktury IV.

Sada 1 - Základy programování

ALG 09. Radix sort (přihrádkové řazení) Counting sort. Přehled asymptotických rychlostí jednotlivých řazení. Ilustrační experiment řazení

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

Algoritmizace prostorových úloh

ADT/ADS = abstraktní datové typy / struktury

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

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ů

Dynamické datové struktury I.

Adresní vyhledávání (přímý přístup, zřetězené a otevřené rozptylování, rozptylovací funkce)

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

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

IB111 Úvod do programování skrze Python

Abstraktní datové typy FRONTA

IAJCE Přednáška č. 9. int[] pole = new int[pocet] int max = pole[0]; int id; for(int i =1; i< pole.length; i++) { // nikoli 0 if (Pole[i] > max) {

Homer. prvky. délka. přední 0 zadní 4. Použití fronty BUS STOP. 3 Lisa. 2 Bart. 4 Maggie. 1 Marge. Grafické znázornění předchozí animace:

Algoritmizace prostorových úloh

Datové struktury. alg12 1

Stromy, haldy, prioritní fronty

Šablony, kontejnery a iterátory

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

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

bfs, dfs, fronta, zásobník, prioritní fronta, halda

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

Algoritmy a datové struktury

Lineární datové struktury

Reprezentace aritmetického výrazu - binární strom reprezentující aritmetický výraz

Konstruktory a destruktory

Základní datové struktury

Časová složitost / Time complexity

Náplň. v Jednoduché příklady na práci s poli v C - Vlastnosti třídění - Způsoby (algoritmy) třídění

TGH07 - Chytré stromové datové struktury

Datový typ prioritní fronta Semestrální práce z předmětu 36PT

Algoritmizace řazení Bubble Sort

Jazyk C++ II. STL knihovna kontejnery část 1

HASHING GENERAL Hashovací (=rozptylovací) funkce

IB108 Sada 1, Příklad 1 Vypracovali: Tomáš Krajča (255676), Martin Milata (256615)

Datové struktury 2: Rozptylovací tabulky

Část I Spojové struktury

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

TGH07 - Chytré stromové datové struktury

Základy algoritmizace. Hašování

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

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

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

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

NPRG030 Programování I, 2018/19 1 / :03:07

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

Konečný automat. Jan Kybic.

Lineární datové struktury

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

NEJKRATŠÍ CESTY I. Doc. RNDr. Josef Kolář, CSc. Katedra teoretické informatiky, FIT České vysoké učení technické v Praze

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

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

PB přednáška (26. října 2015)

A4B33ALG 2010/05 ALG 07. Selection sort (Select sort) Insertion sort (Insert sort) Bubble sort deprecated. Quicksort.

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

Spojové struktury. Spojová struktura (linked structure):

Pokročilá algoritmizace amortizovaná složitost, Fibonacciho halda, počítačová aritmetika

Programování v Pythonu

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

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

Dynamické programování

PG 9.5 novinky ve vývoji aplikací

Stromy. Strom: souvislý graf bez kružnic využití: počítačová grafika seznam objektů efektivní vyhledávání výpočetní stromy rozhodovací stromy

bfs, dfs, fronta, zásobník, prioritní fronta, halda

Šablony, kontejnery a iterátory

Prioritní fronta, halda (heap), řazení

Zadání k 2. programovacímu testu

Prohledávání stavového prostoru

ADT prioritní fronta. Haldy. Další operace nad haldou. Binární halda. Binomické stromy. Časová složitost jednotlivých operací.

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

Chyby a výjimky. Chyba. Odkud se chyby berou? Kdo chyby opravuje? Co můžete dělat jako programátor? Dvě hlavní metody práce s chybami.

Kámen-nůžky-papír. Tomáš Svoboda Centrum strojového vnímání, Katedra kybernetiky Fakulta elektrotechnická, České vysoké učení technické

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

Anotace. Spojové seznamy, haldy. AVL-stromy, A-B stromy. Martin Pergel,

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

Pole a kolekce. v C#, Javě a C++

Dynamické programování

DobSort. Úvod do programování. DobSort Implementace 1/3. DobSort Implementace 2/3. DobSort - Příklad. DobSort Implementace 3/3

IB111 Úvod do programování 1 / 62

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK)

Datové struktury 1: Základní datové struktury

Vzdálenost uzlů v neorientovaném grafu

Bubble sort. příklad. Shaker sort

Stromy. Jan Hnilica Počítačové modelování 14

ˇ razen ı rychlejˇ s ı neˇ z kvadratick e Karel Hor ak, Petr Ryˇsav y 20. dubna 2016 Katedra poˇ c ıtaˇ c u, FEL, ˇ CVUT

přirozený algoritmus seřadí prvky 1,3,2,8,9,7 a prvky 4,5,6 nechává Metody řazení se dělí:

Transkript:

Spojový seznam Jan Kybic http://cmp.felk.cvut.cz/~kybic kybic@fel.cvut.cz 2016 2017 1 / 25

Složitost operací u lineárních datových struktur v Pythonu operace zásob. fronta pole pole řetězce přidej na začátek O(1) O(n) přidej na konec O(1) O(1) O(1) vlož doprostřed O(n) odeber ze začátku O(1) O(1) O(n) odeber kdekoliv O(n) odeber z konce O(1) indexový přístup O(1) O(1) O(1) spojení O(n) O(n) iterace vpřed ano ano ano iterace vzad ano ano ano Přímo nepodporované operace lze implementovat v čase O(n). Konec a začátek jsou zaměnitelné. 2 / 25

Složitost operací u lineárních datových struktur v Pythonu spoj.sez. operace zásob. fronta pole pole řetězce jedn. dvoj. přidej na začátek O(1) O(n) O(1) O(1) přidej na konec O(1) O(1) O(1) O(1) O(1) vlož doprostřed O(n) O(1) O(1) odeber ze začátku O(1) O(1) O(n) O(1) O(1) odeber kdekoliv O(n) O(1) odeber z konce O(1) O(1) indexový přístup O(1) O(1) O(1) spojení O(n) O(n) O(1) O(1) iterace vpřed ano ano ano ano ano iterace vzad ano ano ano ano Přímo nepodporované operace lze implementovat v čase O(n). Konec a začátek jsou zaměnitelné. Jednoduše/dvojitě zřetězený spojový seznam (singly/doubly linked list). pokud máme odkaz na příslušný uzel. O(1), pokud máme odkaz i na předchozí uzel. 2 / 25

Spojový seznam Základní myšlenka: Data jsou součástí uzlů. Uzly = data + odkaz na následníka Uzly dvojitě zřetězeného seznamu obsahují odkaz i na předchůdce. Seznam = odkaz na první uzel. Pokud chceme přidávat na konec, pak potřebujeme odkaz i na poslední uzel. Images courtesy of Brad Miller, David Ranum. 3 / 25

Spojový seznam Základní myšlenka: Data jsou součástí uzlů. Uzly = data + odkaz na následníka Uzly dvojitě zřetězeného seznamu obsahují odkaz i na předchůdce. Seznam = odkaz na první uzel. Pokud chceme přidávat na konec, pak potřebujeme odkaz i na poslední uzel. Images courtesy of Brad Miller, David Ranum. 3 / 25

Reprezentace uzlu class Node: # uzel def init (self,data): self.data = data self.next = None # odkaz na další uzel 4 / 25

Spojový seznam jako zásobník class ListStack: # seznam def init (self): self.head = None def is_empty(self): return self.head is None def push(self,item): node=node(item) node.next=self.head self.head=node def pop(self): item=self.head.data self.head=self.head.next return item def peek(self): return self.head.data Soubor linkedliststack.py. 5 / 25

Spojový seznam jako zásobník příklad s=liststack() s.push(1) s.push(2) s.push(3) print(s.pop()) print(s.pop()) 3 2 s.push(10) print(s.pop()) 10 print(s.is_empty()) False print(s.pop()) 1 print(s.is_empty()) True Soubor linkedlist_examples.py 6 / 25

Spojový seznam jako fronta from linkedliststack import Node,ListStack class ListQueue(ListStack): # zdědíme ListStack def init (self): self.head = None self.last = None # last item self.count = 0 def pop(self): # odeber ze začátku item=self.head.data self.head=self.head.next if self.head is None: self.last=none self.count-=1 return item def dequeue(self): return self.pop() 7 / 25

Spojový seznam jako fronta (2) def push(self,item): # přidej na začátek node=node(item) node.next=self.head if self.head is None: self.last=node self.head=node self.count+=1 def enqueue(self,item): # přidej na konec node=node(item) if self.head is None: # seznam je prázdný self.head=node self.last=node else: self.last.next=node self.last=node self.count+=1 Soubor linkedlistqueue.py 8 / 25

Spojový seznam jako fronta příklad q=listqueue() q.enqueue(1) q.enqueue(2) q.enqueue(3) print(q.dequeue()) print(q.dequeue()) 1 2 q.enqueue(10) print(q.dequeue()) 3 print(q.is_empty()) False print(q.dequeue()) 10 print(q.is_empty()) True Soubor linkedlist_examples.py 9 / 25

Procházení prvků pole linked list traversal Doplníme do třídy ListQueue metody def iter(self,f): """ execute f(x) for all elements x in the queue """ node=self.head while node is not None: f(node.data) node=node.next def reduce(self,f,acc): """ execute acc=f(x,acc) for all x in the queue """ node=self.head while node is not None: acc=f(node.data,acc) node=node.next return acc Soubor linkedlistqueue.py 10 / 25

Konverze na pole a z pole Doplníme do třídy ListQueue metodu def to_array(self): a=[] self.iter(lambda x: a.append(x)) return a Funkce pro vytvoření seznamu z pole def array_to_queue(a): q=listqueue() for x in a: q.enqueue(x) return q Soubor linkedlistqueue.py 11 / 25

Příklady q=array_to_queue([4,2,7,3]) print(q.reduce(max,0)) 7 print(q.reduce(lambda x,acc: acc+x,0)) 16 print(q.to_array()) [4, 2, 7, 3] 12 / 25

Vyhledávání v seznamu Metoda třídy ListQueue, složitost O(n) def contains(self,x): """ returns True if the list contains element x """ node=self.head while node is not None: if node.data==x: return True node=node.next return False 13 / 25

Vyhledávání v seznamu Metoda třídy ListQueue, složitost O(n) def contains(self,x): """ returns True if the list contains element x """ node=self.head while node is not None: if node.data==x: return True node=node.next return False q=array_to_queue([3,52,69,17,19]) print(q.contains(17)) True print(q.contains(20)) False 13 / 25

Mazání v seznamu Metoda třídy ListQueue: def remove(self,x): """ removes an element x, if present """ node=self.head prev=none while node is not None: if node.data==x: if prev is None: self.head=node.next if self.head is None: self.last=none else: prev.next=node.next prev=node node=node.next Soubor linkedlistqueue.py 14 / 25

Mazání v seznamu příklad q=array_to_queue([3,2,5,8,11]) q.remove(5) print(q.to_array()) [3, 2, 8, 11] q.remove(3) print(q.to_array()) [2, 8, 11] q.remove(11) print(q.to_array()) [2, 8] Soubor linkedlist_examples.py 15 / 25

Uspořádaný spojový seznam řazení (Sorted/ordered linked list) Seznam budeme udržovat seřazený. Seznam lze procházet jen odpředu (od self.head). Vkládání (insert) dopředu je rychlejší. Prvky mohou často přicházet srovnané vzestupně (insertion sort) Seznam budeme řadit sestupně, aby větší prvky mohly zůstat vpředu. 16 / 25

Uspořádaný spojový seznam vkládání class OrderedList(ListQueue): def insert(self,x): """ inserts item x in a descending order list""" newnode=node(x) prev=none node=self.head while node is not None and x<node.data: prev=node node=node.next if node is None: # newnode patří na konec if self.head is None: # seznam je prázdný self.head=newnode else: self.last.next=newnode self.last=newnode else: if prev is None: # newnode patří na začátek self.head=newnode else: # newnode patří mezi prev a node prev.next=newnode newnode.next=node self.count+=1 Soubor insertion_sort_linkedlist.py 17 / 25

Řazení vkládáním a spojové seznamy Insertion sort def insertion_sort_linkedlist(a): """ sorts array a inplace in ascending order """ q=orderedlist() for x in a: q.insert(x) for i in range(len(a)-1,-1,-1): a[i]=q.pop() # from the highest value Soubor insertion_sort_linkedlist.py 18 / 25

Řazení vkládáním měření rychlosti 16 14 12 selection_sort insertion_sort insertion_sort_linkedlist 10 time [s] 8 6 4 2 0 0 2000 4000 6000 8000 10000 N 19 / 25

Spojování seznamů v konstantním čase Doplníme do třídy ListQueue metodu def concatenate(self,l): """ destruktivně přidej seznam l na konec """ if l.last is None: return if self.last is None: self.head=l.head else: self.last.next=l.head self.last=l.last self.count+=l.count l.head=none # smaž list l l.last=none l.count=0 Soubor linkedlistqueue.py. 20 / 25

Spojování seznamů příklad q=array_to_queue([1,2,3]) r=array_to_queue([4,5]) q.concatenate(r) print(q.to_array()) [1, 2, 3, 4, 5] Soubor linkedlist_examples.py 21 / 25

Radix sort a spojové seznamy def radix_sort_queue_integers(q): """ setřídí frontu ListQueue přirozených čísel """ max_digits=num_digits(q.reduce(max,0)) for i in range(max_digits): q=sort_queue_by_digit(q,i) return q def sort_queue_by_digit(q,i): prihradka=[ ListQueue() for j in range(10) ] while not q.is_empty(): x=q.dequeue() c=digit(x,i) # číslice pro třídění prihradka[c].enqueue(x) r=listqueue() for p in prihradka: r.concatenate(p) return r Soubor radix_sort_linkedlist.py 22 / 25

Radix sort a spojové seznamy def radix_sort_queue_integers(q): """ setřídí frontu ListQueue přirozených čísel """ max_digits=num_digits(q.reduce(max,0)) for i in range(max_digits): q=sort_queue_by_digit(q,i) return q def sort_queue_by_digit(q,i): prihradka=[ ListQueue() for j in range(10) ] while not q.is_empty(): x=q.dequeue() c=digit(x,i) # číslice pro třídění prihradka[c].enqueue(x) r=listqueue() for p in prihradka: r.concatenate(p) return r V Pythonu se bohužel nevyplatí, režie je příliš velká. Soubor radix_sort_linkedlist.py 22 / 25

Oboustranná fronta (double ended queue) Lineární datová struktura kombinující frontu a zásobník. spoj.sez. operace zásob. fronta oboustranná fronta jedn. dvoj. přidej na začátek O(1) O(1) O(1) O(1) přidej na konec O(1) O(1) O(1) O(1) odeber ze začátku O(1) O(1) O(1) O(1) O(1) odeber z konce O(1) O(n) O(1) iterace vpřed ano ano iterace vzad ano začátek = self.head konec = self.last O(1), pokud máme odkaz i na předchozí uzel. 23 / 25

Aplikace oboustranné fronty Zásobník s omezenou délkou Seznam navštívených stránek v prohlížeči Undo/redo operace v textovém či grafickém editoru Rozvrhování pro více procesorů volné procesory mohou ukrást proces jiným. Nalezení maxima všech souvislých podsekvencí dané délky. 24 / 25

Spojový seznamu shrnutí Podporuje mnoho operací v čase O(1)...... za cenu větších časových a paměťových nároků (konstantní faktor) Pomocí spojového seznamu můžeme implementovat zásobník i frontu. Dvojitě zřetězený spojový seznam umí rychle více operací (iterace vzad, vypuštění prvku uprostřed) za cenu opět větších časových a paměťových nároků (konstantní faktor). 25 / 25