Puud Puu programmeerimises tavaliselt jrjestatud puu dnaamiline andmestruktuur

  • Slides: 58
Download presentation
Puud • Puu (programmeerimises tavaliselt järjestatud puu): - dünaamiline andmestruktuur - komponentideks nn. puu

Puud • Puu (programmeerimises tavaliselt järjestatud puu): - dünaamiline andmestruktuur - komponentideks nn. puu tipud: juurtipp e. juur, vahetipud , lehed - peegeldab ranget hierarhiat: juurtipp on kõige kõrgema taseme “ülemus”, kõigil ülejäänud tippudel on täpselt üks ülemus.

Puud - alluvateta tipud = puu lehed, kõik ülejäänud (v. a. juur) tipud on

Puud - alluvateta tipud = puu lehed, kõik ülejäänud (v. a. juur) tipud on vahetipud - sama ülemuse alluvad – kolleegid, naabrid - järjestatud puu korral on oluline iga tipu alluvate (naabrite) omavaheline järjestus

 • Näide: aritmeetilise avaldise puu “Tavaline” kuju: ( 2 - 1 ) *

• Näide: aritmeetilise avaldise puu “Tavaline” kuju: ( 2 - 1 ) * 4 + 6 / 3 Pööratud poola kuju: 2 1 – 4 * 6 3 / + Prefikskuju sulgudega: + ( * ( - (2, 1), 4), / (6, 3)) Postfikskuju sulgudega: (((2, 1) - , 4) * , (6, 3) / ) + + Juur * / 2 1 4 6 3 Lehed

Puu läbimine • Eesjärjestus (pre-order): - Töödelda juure alampuud järjestuses vasakult paremale • Lõppjärjestus

Puu läbimine • Eesjärjestus (pre-order): - Töödelda juure alampuud järjestuses vasakult paremale • Lõppjärjestus (post-order, end-order): - Töödelda juure alampuud järjestuses vasakult paremale - Töödelda juur Millises järjestuses toimub aritmeetilise avaldise väärtuse arvutamine?

Puu läbimine A B Pre: ABDGHEFICJ Post: GHDEIFBJCA C D E F J G

Puu läbimine A B Pre: ABDGHEFICJ Post: GHDEIFBJCA C D E F J G H I

Puu esitlusviisid • Graafiline (joonisel) • Vasakpoolne suluesitus A(B(D(G, H), E, F(I)), C(J)) •

Puu esitlusviisid • Graafiline (joonisel) • Vasakpoolne suluesitus A(B(D(G, H), E, F(I)), C(J)) • Parempoolne suluesitus (((G, H)D, E(I)F)B, (J)C)A • Tekstiline “treppimine”

Puu esitlusviisid • Tekstiline “treppimine” A B D G H E F I C

Puu esitlusviisid • Tekstiline “treppimine” A B D G H E F I C J

Puu esitlusviisid • Tippudele viitamine liitnimedega A, A. B, A. C, A. B. D,

Puu esitlusviisid • Tippudele viitamine liitnimedega A, A. B, A. C, A. B. D, A. B. E, A. B. F, A. B. D. G, A. B. D. H, A. B. F. I, A. C. J • Mittejärjestatud puu esitamiseks sobivad ka graafi esitlusviisid (vajadusel fikseerida juurtipp) – näit. külgnevusmaatriks vms.

Puu esitlusviisid • Puu esitlusviisid töötlemiseks arvutis sõltuvad lahendatavast ülesandest – universaalset “parimat” kujutlusviisi

Puu esitlusviisid • Puu esitlusviisid töötlemiseks arvutis sõltuvad lahendatavast ülesandest – universaalset “parimat” kujutlusviisi ei leidu: - tekstilised esitlused - viidastruktuurid - peitmine muude mehhanismide sisse -…

Puu kujutamine ahelate abil • Igas tipus on viit tema ülemusele (juurtipus nullviit). •

Puu kujutamine ahelate abil • Igas tipus on viit tema ülemusele (juurtipus nullviit). • Puudus: puu tippe ei saa lähtudes juurtipust süstemaatiliselt “läbi käia”. Saab teha töötlust “alt üles”, kui on korraldatud juurdepääs lehtede hulgale

Puu kujutamine ahelate abil • Igast tipust lähtub selle tipu vahetute alluvate ahel (lehtede

Puu kujutamine ahelate abil • Igast tipust lähtub selle tipu vahetute alluvate ahel (lehtede korral tühi ahel) ning viit (parempoolsele) naabrile. • Puudus: antud tipust ei pääse lisavõimalusi (näit. magasini) kasutama “üles”. • Kasulik rekursiivsete töötlusprogrammide korral.

Puu kujutamine arvutis • Nn. kahendpuu tipus on viit vasakule alampuule ning viit paremale

Puu kujutamine arvutis • Nn. kahendpuu tipus on viit vasakule alampuule ning viit paremale alampuule. • Läbimiseks kasutada magasini või rekursiivset algoritmi.

I import java. util. *; /** Puu tipp. Käsitleme puu tippu ka alampuu juurena

I import java. util. *; /** Puu tipp. Käsitleme puu tippu ka alampuu juurena ning * naabrite loetelu elemendina. */ public class Tipp implements java. util. Enumeration { /** tippu identifitseeriv sõne. */ String nimi; /** viit tipu parempoolsele naabrile või null. */ Tipp parem. Naaber; /** viit tipu esimesele alluvale või null. */ Tipp esim. Alluv;

/** tipu konstruktor. */ Tipp (String s, Tipp p, Tipp a) { pane. Nimi

/** tipu konstruktor. */ Tipp (String s, Tipp p, Tipp a) { pane. Nimi (s); pane. Parem. Naaber (p); pane. Esim. Alluv (a); } Tipp() { this ("", null); } Tipp (String s) { this (s, null); } Tipp (String s, Tipp p) { this (s, p, null); } /** teisene konstruktor. */

/** nime panemine. */ public void pane. Nimi(String s) { nimi = s; }

/** nime panemine. */ public void pane. Nimi(String s) { nimi = s; } /** tagastab nime. */ public String vota. Nimi() { return nimi; } /** väärtustab viida parempoolsele naabrile. */ public void pane. Parem. Naaber (Tipp p) { parem. Naaber = p; }

/** tagastab parempoolse naabri. */ public Tipp vota. Parem. Naaber() { return parem. Naaber;

/** tagastab parempoolse naabri. */ public Tipp vota. Parem. Naaber() { return parem. Naaber; } /** väärtustab viida esimesele alluvale. */ public void pane. Esim. Alluv (Tipp a) { esim. Alluv = a; } /** tagastab esimese alluva. */ public Tipp vota. Esim. Alluv() { return esim. Alluv; }

/** teisendus sõneks (ainult tipp) */ public String to. String() { return vota. Nimi();

/** teisendus sõneks (ainult tipp) */ public String to. String() { return vota. Nimi(); } /** tipu töötlemine (katta üle alamklassides). */ public void tootle. Tipp() { System. out. print (vota. Nimi() + " "); } /** naabrite Enumeration. */ public boolean has. More. Elements() { return (vota. Parem. Naaber() != null); }

/** naabrite Enumeration. */ public Object next. Element() { return vota. Parem. Naaber(); }

/** naabrite Enumeration. */ public Object next. Element() { return vota. Parem. Naaber(); } /** alluvate loetelu. */ public Enumeration alluvad() { return vota. Esim. Alluv(); } /** kas tipp on leht. */ public boolean on. Leht() { return (vota. Esim. Alluv() == null); }

/** alluva lisamine viimaseks alluvate loetelus. */ public void lisa. Alluv (Tipp a) {

/** alluva lisamine viimaseks alluvate loetelus. */ public void lisa. Alluv (Tipp a) { if (a == null) return; Enumeration alluvad = alluvad(); if (alluvad == null) pane. Esim. Alluv (a); else { while (alluvad. has. More. Elements()) alluvad = (Tipp)alluvad. next. Element(); ((Tipp)alluvad). pane. Parem. Naaber (a); } }

public int size() { /** (alam)puu tippude arv (koos juurega). */ int n =

public int size() { /** (alam)puu tippude arv (koos juurega). */ int n = 1; // juur ise Enumeration alluvad = alluvad(); while (alluvad != null) { n = n + ((Tipp)alluvad). size(); alluvad = (Tipp)alluvad. next. Element(); } return n; } public void preorder() { /** puu läbimine eesjärjekorras. */ tootle. Tipp(); Enumeration alluvad = alluvad(); while (alluvad != null) { ((Tipp)alluvad). preorder(); alluvad = (Tipp)alluvad. next. Element(); } }

/** puu läbimine lõppjärjekorras. */ public void postorder() { Enumeration alluvad = alluvad(); while

/** puu läbimine lõppjärjekorras. */ public void postorder() { Enumeration alluvad = alluvad(); while (alluvad != null) { ((Tipp)alluvad). postorder(); alluvad = (Tipp)alluvad. next. Element(); } tootle. Tipp(); }

/** konkreetse puu tegemine. */ public static Tipp teha. Puu() { Tipp juur =

/** konkreetse puu tegemine. */ public static Tipp teha. Puu() { Tipp juur = new Tipp ("+", null, new Tipp ("*", new Tipp ("/", null, new Tipp ("6", new Tipp ("3", null), null)), new Tipp ("-", new Tipp ("4", null), new Tipp ("2", new Tipp ("1", null), null)))); return juur; }

/** peameetod silumiseks. */ public static void main (String[] param) { Tipp t =

/** peameetod silumiseks. */ public static void main (String[] param) { Tipp t = teha. Puu(); System. out. println (t. size()); System. out. print ("Preorder: "); t. preorder(); System. out. println(); System. out. print ("Postorder: "); t. postorder(); System. out. println(); } // main lõpp

Graafid • • • G=(V, E), V-lõplik tippude hulk E on alamhulk hulgast V

Graafid • • • G=(V, E), V-lõplik tippude hulk E on alamhulk hulgast V V Orienteerimata graafid Orienteeritud graafid E nim. servade hulgaks

Graafid • G=(V, Ø) – nullgraaf • Täisgraaf G={V, V×V{v, v} v V} •

Graafid • G=(V, Ø) – nullgraaf • Täisgraaf G={V, V×V{v, v} v V} • Tee tipust u tippu v on tippude jada (u, w 0), (w 0, w 1), …(wn, v), kus kõik need paarid on servad. • Sidus graaf • Nõrgalt sidus – suundade ärajätmisel saab sidusaks

Graafid • G 1=(V 1, E 1) on graafi G=(V, E) alamgraaf, kui V

Graafid • G 1=(V 1, E 1) on graafi G=(V, E) alamgraaf, kui V 1 V ja E 1=E V 1 • Külgnevusmaatriks on |V | | V| maatriks A=a[i][j], milles a[i][j]=1, kui kaar (i, j) E ning 0 vastasel juhul. • Multigraafi korral a[i][j] tipust i tippu j viivate teede arv

Graafid • Graafi G transitiivne sulund G+ saadakse lähtegraafile kõigi niisuguste kaarte (u, v)

Graafid • Graafi G transitiivne sulund G+ saadakse lähtegraafile kõigi niisuguste kaarte (u, v) lisamisel, mille korral leidub tee tipust u tippu v • Ahel – tee, milles servad ei kordu • Lihtahel – ahel, milles ka tipud ei kordu • Tsükkel – nullist suurema pikkusega kinnine ahel • Lihttsükkel – kinnine lihtahel • Euleri ja Hamiltoni ahelad, tsüklid

Graafid • Kauguste maatriks D=d[i][j] on |V | | V | maatriks, milles d[i][j]

Graafid • Kauguste maatriks D=d[i][j] on |V | | V | maatriks, milles d[i][j] on kaare (i, j) “pikkus” • Adj(v)={e E | w V: e=(v, w)} • Külgnevusstruktuur on hulk {(v, Adj(v)) | v V}

Graafide kujutamine • Joonis (nt. tasandilised graafid) • Kaarte loetelu (kaarega peab siis lisanduma

Graafide kujutamine • Joonis (nt. tasandilised graafid) • Kaarte loetelu (kaarega peab siis lisanduma ka otspunktide kohta käiv informatsioon) • Külgnevusmaatriks (kaaslusmaatriks) • Külgnevusstruktuur – tippude loetelu, milles iga tipuga seotud sellest lähtuvate kaarte loetelu, kaare suubumistipud

Graafi kujutamine külgnevusstruktuuri abil

Graafi kujutamine külgnevusstruktuuri abil

Graafi kujutamine külgnevusstruktuuri abil

Graafi kujutamine külgnevusstruktuuri abil

interface Abstr. Graaf { boolean lisa. Tipp (Abstr. Tipp t); //kas sai lisada? boolean

interface Abstr. Graaf { boolean lisa. Tipp (Abstr. Tipp t); //kas sai lisada? boolean eemalda. Tipp (Abstr. Tipp t); //kas sai eemaldada? Abstr. Tipp leia. Tipp (String nimi); //nime jargi tipu leidmine String to. String (); //va"ljatru"kiks vajalik }

interface Abstr. Tipp { String vota. Nimi (); //tipu nime leidmine boolean lisa. Valjuvkaar

interface Abstr. Tipp { String vota. Nimi (); //tipu nime leidmine boolean lisa. Valjuvkaar (Abstr. Kaar k); //kas sai lisada? boolean eemalda. Valjuvkaar (Abstr. Kaar k); //kas sai eemaldada? }

interface Abstr. Kaar { boolean pane. Suubuma (Abstr. Tipp t); String vota. Nimi ();

interface Abstr. Kaar { boolean pane. Suubuma (Abstr. Tipp t); String vota. Nimi (); //kaare nime leidmine }

class Element { //lisainfo tuleb lisada alamklassides String nimi; Element jargmine; Element() { //konstruktor

class Element { //lisainfo tuleb lisada alamklassides String nimi; Element jargmine; Element() { //konstruktor vaikimisi } Element (String s) { //konstruktor nimega isendite loomiseks pane. Nimi (s); } public String vota. Nimi() { return nimi; } public Element vota. Jargmine() { return jargmine;

public Element vota. Jargmine() { return jargmine; } public void pane. Nimi (String s)

public Element vota. Jargmine() { return jargmine; } public void pane. Nimi (String s) { nimi = s; } public void pane. Jargmine (Element e) { jargmine = e; }

public Element lisa (Element e) { //annab uue alguse tagasi if (e == null)

public Element lisa (Element e) { //annab uue alguse tagasi if (e == null) return this; // ei olnudki soovi lisada if (e == this) return this; // ebanormaalne situatsioon niikuinii if (e. vota. Nimi(). compare. To (vota. Nimi()) < 0) { // e. nimi < this. nimi e. pane. Jargmine (this); // lisamine ahela algusesse return e; } Element abi = this; // hakkame kohta otsima abi jarele while (abi. vota. Jargmine() != null) { if (e. vota. Nimi(). compare. To (abi. vota. Jargmine(). vota. Nimi()) < 0) { // lisamine abi jarele e. pane. Jargmine (abi. vota. Jargmine()); abi. pane. Jargmine (e); return this; } abi = abi. vota. Jargmine(); }

abi. pane. Jargmine (e); // lisamine ahela loppu e. pane. Jargmine (null); // igaks

abi. pane. Jargmine (e); // lisamine ahela loppu e. pane. Jargmine (null); // igaks juhuks return this; } // lisa() lopp public Element eemalda (Element e) { if (e == null) return this; //annab uue alguse voi null //ei eemalda midagi if (e == this) return vota. Jargmine(); //esimese eemaldamine Element abi = this; while (abi != null) { if (e == abi. vota. Jargmine()) { abi. pane. Jargmine (e. vota. Jargmine()); } abi = abi. vota. Jargmine(); } return this;

public Element otsi (String s) { //kui ei leia, siis null Element abi =

public Element otsi (String s) { //kui ei leia, siis null Element abi = this; while (abi != null) { if (s. equals (abi. vota. Nimi())) return abi; abi = abi. vota. Jargmine(); } return null; } } //Element lopp

class Graaf extends Element implements Abstr. Graaf { Tipp esimene; Graaf () { //konstruktor

class Graaf extends Element implements Abstr. Graaf { Tipp esimene; Graaf () { //konstruktor vaikimisi } Graaf (String s) { //konstruktor nimega graafi jaoks super(s); } public Tipp vota. Esimene () { return esimene; } public void pane. Esimene (Tipp t) { esimene = t; }

public boolean lisa. Tipp (Abstr. Tipp t) { if (vota. Esimene() == null) {

public boolean lisa. Tipp (Abstr. Tipp t) { if (vota. Esimene() == null) { pane. Esimene ((Tipp) t); return true; } pane. Esimene ((Tipp) vota. Esimene(). lisa ((Tipp) t)); return true; }

public boolean eemalda. Tipp (Abstr. Tipp t) { if (vota. Esimene() == null) return

public boolean eemalda. Tipp (Abstr. Tipp t) { if (vota. Esimene() == null) return false; pane. Esimene ((Tipp) vota. Esimene(). eemalda ((Tipp) t)); return true; } public Abstr. Tipp leia. Tipp (String s) { if (vota. Esimene() == null) return null; return (Tipp) vota. Esimene(). otsi (s); }

public String to. String () { String abi = "Graaf: " + vota. Nimi()

public String to. String () { String abi = "Graaf: " + vota. Nimi() + "n"; Tipp t = vota. Esimene(); while (t != null) { abi += t. vota. Nimi() + " --> "; Kaar k = t. vota. Esimenevaljuv(); while (k != null) { abi += k. vota. Kuhusuubub(). vota. Nimi() + " (" + k. vota. Nimi() + ") "; k = (Kaar) k. vota. Jargmine(); } abi += "n"; t = (Tipp) t. vota. Jargmine(); } return abi; } } //Graaf lopp

class Tipp extends Element implements Abstr. Tipp { Kaar esimenevaljuv; Tipp () { //konstruktor

class Tipp extends Element implements Abstr. Tipp { Kaar esimenevaljuv; Tipp () { //konstruktor vaikimisi } Tipp (String s) { //konstruktor nimega tipule super (s); } public Kaar vota. Esimenevaljuv () { return esimenevaljuv; } public void pane. Esimenevaljuv (Kaar k) { esimenevaljuv = k; }

public boolean lisa. Valjuvkaar (Abstr. Kaar k) { if (vota. Esimenevaljuv () == null)

public boolean lisa. Valjuvkaar (Abstr. Kaar k) { if (vota. Esimenevaljuv () == null) { pane. Esimenevaljuv ((Kaar) k); return true; } pane. Esimenevaljuv ((Kaar) vota. Esimenevaljuv(). lisa ((Kaar) k)); return true; } public boolean eemalda. Valjuvkaar (Abstr. Kaar k) { if (vota. Esimenevaljuv () == null) return false; pane. Esimenevaljuv ((Kaar) vota. Esimenevaljuv(). eemalda ((Kaar) k)); return true; } } //Tipp lopp

class Kaar extends Element implements Abstr. Kaar { Tipp kuhusuubub; Kaar () { //konstruktor

class Kaar extends Element implements Abstr. Kaar { Tipp kuhusuubub; Kaar () { //konstruktor vaikimisi } Kaar (String s) { //konstruktor nimega kaarele super (s); } public Tipp vota. Kuhusuubub () { return kuhusuubub; }

public void pane. Kuhusuubub (Tipp t) { kuhusuubub = t; } public boolean pane.

public void pane. Kuhusuubub (Tipp t) { kuhusuubub = t; } public boolean pane. Suubuma (Abstr. Tipp t) { pane. Kuhusuubub ((Tipp) t); return t != null; } } //Kaar lopp

static public void main (String[] argumendid) { System. out. println ("Tere"); Graaf g =

static public void main (String[] argumendid) { System. out. println ("Tere"); Graaf g = new Graaf ("minugraaf"); Tipp t 1 = new Tipp ("T 1"); Kaar k 1 = new Kaar ("K 1"); g. lisa. Tipp (t 1); Tipp t 2 = new Tipp(); t 2. pane. Nimi ("T 0"); g. lisa. Tipp (t 2); t 1. lisa. Valjuvkaar (k 1); k 1. pane. Suubuma (t 2); System. out. println (g); //oluline, et to. String() meetod oleks! System. out. println ("Lopp"); }

Programmi töö: Tere Graaf: minugraaf T 0 --> T 1 --> T 0 (K

Programmi töö: Tere Graaf: minugraaf T 0 --> T 1 --> T 0 (K 1) Lopp

Külgnevusstruktuuri läbivaatus • Kuidas läbida graafi? • “Töödelda” tipud ja kaared. • Kasutusel abimuutujad

Külgnevusstruktuuri läbivaatus • Kuidas läbida graafi? • “Töödelda” tipud ja kaared. • Kasutusel abimuutujad tippude ja kaarte läbimiseks

Külgnevusmaatriksi ehitamine • Algul kõik M[i][j]=0 • Iga kaare korral M[kaare_algus][kaare_lopp]++ • Mida selle

Külgnevusmaatriksi ehitamine • Algul kõik M[i][j]=0 • Iga kaare korral M[kaare_algus][kaare_lopp]++ • Mida selle maatriksiga teha? • Tehted maatriksitega, interpretatsioon • Näiteks: M – linnadevaheliste lennuliinide olemasolu

Kauguste arvutamine • Etteantud külgnevusmaatriksi järgi leida lühimad teepikkused kõigi tipupaaride vahe → kauguste

Kauguste arvutamine • Etteantud külgnevusmaatriksi järgi leida lühimad teepikkused kõigi tipupaaride vahe → kauguste maatriks • Floyd-Warshalli algoritmi idee: iga tipu t korral vaadata läbi kõikvõimalikud teed kujul i→t→j. • t=1. . n i=1. . n j=1. . n if (M[i][t]+M[t][j]<M[i][j]) M[i][j]=M[i][t]+M[t][j]; • Keerukuseks O(n 3)

Tsükliteta orienteeritud graafi tippude topoloogiline sorteerimine • Leida graafi tippude selline transitiivne järjestus <<,

Tsükliteta orienteeritud graafi tippude topoloogiline sorteerimine • Leida graafi tippude selline transitiivne järjestus <<, mille korral mistahes kaare (vi, vj) korral vi<<vj • Igal sammul eemaldatakse graafil üks eellasteta tipp. Tegelikul kasutusel konkretiseerida • Ehituste planeering. Tööde tähtajad. Näide DME õpikust (lk. 86, ül. 24)

Graafi läbimise üldjuht • t olgu algtipp • Adj(v)={e E | w V: e=(v,

Graafi läbimise üldjuht • t olgu algtipp • Adj(v)={e E | w V: e=(v, w)} • Iga v V korral olek(v)=“uus”|”järjekorras”|”töödeldud” • Q – järjekord (tippude hulk) • Kuidas panna tippe järjekorda? Magasini? Kumb valida?

Graafi läbimine • Laiuti, Q on tavaline järjekord – FIFO • Sügavuti, Q on

Graafi läbimine • Laiuti, Q on tavaline järjekord – FIFO • Sügavuti, Q on magasin – LIFO • Sõltuvalt ülesandest, nt. Djikstra algoritmis (vaatleme järgmises loengus) lühimate teede leidmiseks on Q muutuvate eelistustega järjekord • Kas aritmeetikaavaldist kujutava puu “väärtuse” arvutamisel kasutame magasini või järjekorda?

Kaarte pikkused on võrdsed

Kaarte pikkused on võrdsed

Kaarte pikkused ei ole võrdsed

Kaarte pikkused ei ole võrdsed

Veel • Ülesanne: leida minimaalse kaarte arvuga tee antud tipust kõigisse teistesse tippudesse •

Veel • Ülesanne: leida minimaalse kaarte arvuga tee antud tipust kõigisse teistesse tippudesse • Lühimate teede erijuht, kui kaarte kaalud võrdsed • Graafi läbimine laiuti, kus järjekorrast võetud tipu v järglased seotakse ahelasse: eellane(w)=v • Kaarte arvu minimaalsuse tagab läbimise järjekord