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

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

ABSTRAKTNÍ DATOVÉ TYPY (ADT)

Rekurze a zásobník. Jak se vypočítá rekurzivní program? volání metody. vyšší adresy. main(){... fa(); //push ret1... } ret1

Řazení. Uspořádat množinu prvků obsahujících klíč podle definovaného kriteria.

Dynamické datové struktury III.

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

Stromy, haldy, prioritní fronty

Dynamické datové struktury IV.

Datové struktury. alg12 1

Základní datové struktury III: Stromy, haldy

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

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

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

Časová složitost algoritmů

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

Prioritní fronta, halda

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

Algoritmy a datové struktury

Algoritmy na ohodnoceném grafu

Konstruktory a destruktory

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

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

TGH07 - Chytré stromové datové struktury

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

TGH07 - Chytré stromové datové struktury

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

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

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

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

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

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

Binární Vyhledávací Stromy, u kterých je. složitost operací v nejhorším. rovná O(log n)

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

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) {

Select sort: krok 1: krok 2: krok 3: atd. celkem porovnání. výběr nejmenšího klíče z n prvků vyžaduje 1 porovnání

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

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

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

Základy algoritmizace c2005, 2007 Michal Krátký, Jiří Dvorský1/39

Volné stromy. Úvod do programování. Kořenové stromy a seřazené stromy. Volné stromy

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

Abstraktní datové typy

Intervalové stromy. Představme si, že máme posloupnost celých čísel p 0, p 1,... p N 1, se kterou budeme. 1. Změna jednoho čísla v posloupnosti.

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.

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

ADT/ADS = abstraktní datové typy / struktury

STROMOVE ALGORITMY Prohledavani do sirky (level-order) Po vodorovnejch carach fronta

bin arn ı vyhled av an ı a bst Karel Hor ak, Petr Ryˇsav y 23. bˇrezna 2016 Katedra poˇ c ıtaˇ c u, FEL, ˇ CVUT

1. Téma 12 - Textové soubory a výjimky

Abstraktní datové typy: zásobník

Abstraktní datové typy FRONTA

Základní datové struktury

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

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

AVL stromy. pro každý uzel u stromu platí, že rozdíl mezi výškou jeho levého a pravého podstromu je nejvýše 1 stromy jsou samovyvažující

Red Black strom (Red Black Tree) Úvod do programování. Rotace. Red Black strom. Rotace. Rotace

ADT Seznam. dynamická množina. prvky vkládáme a vyjímáme na libovolné pozici (místě) v jejich posloupnosti (sekvenci) zásobník a fronta vs.

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:

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

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

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

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

Spojové struktury. x, y, a, b. X1 y1 X2 y2 X3 y3. Grafické objekty bod. kružnice. obdélník. lomenáčára

Pokročilé haldy. prof. Ing. Pavel Tvrdík CSc. Fakulta informačních technologií České vysoké učení technické v Praze c Pavel Tvrdík, 2010

Dynamické programování. Optimální binární vyhledávací strom

Časová složitost algoritmů, řazení a vyhledávání

Vyhledávací stromy. Slouží jako pomůcka pro organizaci dat umožňující efektivní vyhledávání.

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

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

Vyvažování a rotace v BVS, všude se předpokládá AVL strom

Algoritmy I, složitost

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

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

Dynamické datové struktury I.

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

Algoritmizace a programování

Algoritmizace prostorových úloh

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

Tabulka. Často jde nejenom o dynamickou množinu, ale i statickou množinu. Matematické tabulky statická množina

Spojový seznam. Jan Kybic.

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

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

Vypracované okruhy z PPA2 2008

Binární vyhledávací strom pomocí směrníků Miroslav Hostaša L06620

Informatika navazující magisterské studium Přijímací zkouška z informatiky 2018 varianta A

Kolekce, cyklus foreach

Vyhledávání. doc. Mgr. Jiří Dvorský, Ph.D. Katedra informatiky Fakulta elektrotechniky a informatiky VŠB TU Ostrava. Prezentace ke dni 21.

Java - řazení objektů

Obsah přednášky. 12. Dokumentace zdrojového kódu Tvorba elektronické dokumentace UML. Co je diagram tříd. Ing. Ondřej Guth

Šablony, kontejnery a iterátory

Maturitní téma: Programovací jazyk JAVA

Algoritmy výpočetní geometrie

TGH05 - Problém za milion dolarů.

Stromy. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta a kol.

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

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

Základy algoritmizace. Hašování

3 Algoritmy řazení. prvku a 1 je rovněž seřazená.

10 Generické implementace

Implementace LL(1) překladů

Transkript:

Prioritní fronta, halda (heap), řazení Co je prioritní fronta? Definována operacemi - vlož prvek - vyber největší (nejmenší) prvek Proč pf? Rozhraní: class PF { // ADT rozhrani PF(); boolean jeprazdna(); void vloz(prvek); Prvek vybermax(); // vytvoření prázdné prioritní fronty // test, je-li prázdná // vložení prvku // výběr největšího prvku další možná operace nalezení, přečtení největšího prvku

Implementace ADT prioritní fronta pomocí pole Myšlenka: pole je uspořádáno vzestupně 1. vybermax odebere poslední prvek :-) 2. vlož větší prvky posuneme doprava o jednu pozici :-( class PF { private int[] pf; private int pocet; final int maxn=10; PF() { pf = new int[maxn]; pocet = 0; boolean jeprazdna() { return (pocet == 0); void vloz(int klic) { if (pocet == 0) pf[0] = klic; else { // hledame index vlozeni i int i = pocet; while (i > 0 && pf[i - 1] > klic) { pf[i] = pf[i - 1]; --i; pf[i] = klic; pocet++; int vybermax() { return pf[--pocet];

Jiná myšlenka: pole prvků není uspořádáno 1. vlož přidej na konec pole :-) 2. vybermax najdi největší :-( class PF { private int[] pf; private int pocet; final int maxn=10; PF() { pf = new int[maxn]; pocet = 0; boolean jeprazdna() { return (pocet == 0); void vloz(int klic) { pf[pocet++] = klic; int vybermax() { int max = 0; //index max prvku for (int i = 1; i < pocet; i++) if (pf[max] < pf[i]) max =i; int t = pf[max]; //vymenime max a pf[max] = pf[pocet - 1]; //posledni pf[pocet - 1] = t; return pf[--pocet];

Implementace ADT prioritní fronta pomocí spojového seznamu Myšlenka: pomůže neuspořádaný seznam? vlož přidej na začátek seznamu :-) vybermax najdi největší :-( class PF { private class Prvek { int klic; Prvek dalsi; Prvek predch; Prvek() { Prvek(int klic) { this.klic = klic; this.dalsi = null; this.predch = null; private Prvek hlavicka; PF () { hlavicka = new Prvek(); hlavicka.dalsi = hlavicka; hlavicka.predch = hlavicka; boolean jeprazdna() { return (hlavicka.dalsi == hlavicka.dalsi.dalsi);

void vloz(int klic) { Prvek novy = new Prvek(klic); novy.dalsi = hlavicka.dalsi; novy.predch = hlavicka; hlavicka.dalsi.predch = novy; hlavicka.dalsi = novy; int vybermax() { Prvek x = hlavicka.dalsi; for (Prvek t = x.dalsi; t!= hlavicka; t = t.dalsi) if (x.klic < t.klic) x = t; //x ukazatel na max prvek int max = x.klic; x.predch.dalsi = x.dalsi; x.dalsi.predch = x.predch; return max; // opravit eknihu Myšlenka: pomůže uspořádaný seznam? vybermax vyber prvek ze začátku seznamu :-) vlož vlož před první menší prvek nebo na konec :-(

Složitost: vlož vyber největší najdi největší prvek prvek uspořádané pole N 1 1 uspořádaný seznam N 1 1 neuspořádané pole 1 N N neuspořádaný seznam 1 N N Jakou implementaci zvolíme, potřebujeme-li v aplikaci často zjistit největší prvek a zřídka vložit prvek? trpělivý (lazy) přístup vs. netrpělivý (eager) přístup neuděláme co nemusíme vs. uděláme hned co můžeme a máme práci později a později máme klid (pouze vložíme) (vložíme a uspořádáme)

Implementace prioritní fronty pomocí BVS Myšlenka: operace vložení a nalezení prvku se zadaným klíčem byly O(h), kde h je výška stromu vybermax: int vybermax() { DVrchol x = koren; DVrchol predch = null; while (x.pravy!= null) { predch = x; x = x.pravy; if (x == koren) koren = koren.levy; else predch.pravy = x.levy; return x.klic; x koren

koren x -operace vložení, nalezení i výběru největšího prvku jsou O(h) -nejhorší případ h=n-1 -průměrný případ h=1,39log 2 N Umíme zlepšit?

Halda (heap) Myšlenka: N prvků můžeme uložit v úplném binárním stromě s výškou h=θ(log 2 N) - všechny úrovně jsou zaplněny, poslední zleva do počtu prvků vlastnost haldy - klíč v každém vrcholu je větší nebo roven klíčům v jeho následnících, pokud je má - kořen je největší prvek Halda je úplný binární strom s vlastností haldy reprezentován pomocí pole. - přesněji max-halda, obdobně min-halda nalezení největšího prvku je O(1) - první prvek pole

vybermax: vybereme kořen (první prvek pole) a nahradíme ho posledním prvkem - strom zůstal úplným binárním stromem - mohla být porušena vlastnost haldy - obnovení vlastnosti haldy: nový kořen vyměníme s větším z jeho následníků,..., dokud není obnovena vlastnost haldy // kořen haldy má index 1 // poslední prvek má index pocet // metoda dolu() začne obnovu haldy od indexu k // pro vybermax bude k=1 private void dolu(int k, int pocet) { // levy následník má index 2k while (2*k <= pocet) { int j = 2*k; // exituje-li pravý následník j < pocet, // j bude index většího z obou následníků if (j < pocet && pf[j] < pf[j+1]) j++; if (pf[k] >= pf[j]) break; // obnoveno vymen(k,j); k = j;

vloz: přidáme prvek na konec pole - mohla být porušena vlastnost haldy - obnovení vlastnosti haldy: vyměníme ho s předchůdcem,..., dokud není obnovena vlastnost haldy // metoda nahoru() začne obnovu haldy od indexu k // pro vloz bude k=pocet private void nahoru(int k) { // předchůdce má index k/2 while (k > 1 && pf[k/2] < pf[k]) { vymen(k, k/2); k = k/2;

class PF { private void dolu... ; private void nahoru... ; private void vymen... ; private int[] pf; final int maxn = 10; private int pocet; PF() { pf = new int[maxn + 1]; pocet = 0; boolean jeprazdna() { return pocet == 0; void vloz(int klic) { pf[++pocet] = klic; nahoru(pocet); int vybermax() { vymen(1,pocet); dolu(1, pocet - 1); return pf[pocet--];

vybermax potřebuje nejvíce 2log 2 N porovnání vlož potřebuje nejvíce log 2 N porovnání operace jsou O(log N) vytvoření haldy s N prvky postupným vkládáním prvků operací vlož v nejhorším případě je: log 2 N +... + log 2 2 + log 2 1 < N log 2 N

Řazení a prioritní fronta class RazeniPole { //ADT rozhrani void nactiprvek(int) void tiskpole() void razenipf() Implementace metod nactiprvek() a tiskprvku() class RazeniPole { private int[] pole; private int pocet; final int maxn; RazeniPole() { pole = new int[maxn]; pocet = 0; void nactiprvek(int klic) { pole[pocet] = klic; pocet++; void tiskpole() { for(int i = 0; i < pocet; i++) Sytem.out.print(pole[i]+ " "); System.out.println(" ");

Myšlenka: 1. vytvoříme prioritní frontu 2. vybíráme největší prvek a ukládáme od konce původního pole void razenipf() { PF pf = new PF(); int i; // z pole vložíme prvky do prioritní fronty for(i = 0; i < pocet; i++) pf.vloz(pole[i]); // do pole je uložíme operací vybermax for(i = pocet-1; i >= 0; i--) pole[i] = pf.vybermax(); Zkuste si klienta RazeniPole s různými imlementacemi třídy PF! - metoda razenipf()obecně neřadí na místě PF uspořádaným polem vede na metodu řazení typu řazení vkládáním PF neuspořádaným polem vede na metodu, která odpovídá řazení výběrem

PF pomocí haldy vytvoření N log 2 N vybíraní největšího prvku je log 2 N +... + log 2 2 + log 2 1 < N log 2 N řazení je N log 2 N implementace 1. v poli vytvoříme haldu o dvou, třech,..., pocet prvcích 2. největší prvek vyměníme s posledním a obnovíme haldu o jeden prvek menší class RazeniPoleHaldou1 { private void vymen(int i, int j) { int t = pf[i]; pf[i] = pf[j]; pf[j] = t; private void dolu(int k, int pocet) { while (2*k <= pocet) { int j = 2*k; if (j < pocet && pf[j] < pf[j+1]) j++; if (pf[k] >= pf[j]) break; vymen(k,j); k = j; private void nahoru(int k) { while (k > 1 && pf[k/2] < pf[k]) { vymen(k, k/2); k = k/2;

private int[] pf; private int pocet; final int maxn=10; RazeniPoleHaldou1() { pf = new int[maxn + 1]; pocet = 0; void nactiprvek(int klic) { pf[++pocet] = klic; void tiskpole () { for(int i = 1; i <= pocet; i++) System.out.print(pf[i]+" "); System.out.println(" "); void razenihaldou1() { int i = 1; // postupně vytvoříme v poli pf haldu // velikosti i=1,..., pocet while (i < pocet) nahoru(++i); // největší prvek vyměníme s posledním a // obnovíme haldu o 1 menší while (i > 1) { vymen(1,i); dolu(1,--i);