Tietorakenteet ja algoritmit II Loppuraportti, ryhmä 7



Samankaltaiset tiedostot
3. Binääripuu, Java-toteutus

Hakupuut. tässä luvussa tarkastelemme puita tiedon tallennusrakenteina

Tietorakenteet, laskuharjoitus 6,

Ohjelmoinnin jatkokurssi, kurssikoe

1 Tehtävän kuvaus ja analysointi

Listarakenne (ArrayList-luokka)

Algoritmit 2. Luento 2 Ke Timo Männikkö

Algoritmit 2. Luento 2 To Timo Männikkö

Ohjelmointi 2 / 2008 Välikoe / Pöytätestaa seuraava ohjelma.

A TIETORAKENTEET JA ALGORITMIT

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

Ohjelmointi 2 / 2010 Välikoe / 26.3

Algoritmit 1. Luento 7 Ti Timo Männikkö

Tehtävän V.1 ratkaisuehdotus Tietorakenteet, syksy 2003

Olio-ohjelmointi Javalla

TIETORAKENTEET JA ALGORITMIT

Tietokannat II -kurssin harjoitustyö

Binäärihaun vertailujärjestys

private TreeMap<String, Opiskelija> nimella; private TreeMap<String, Opiskelija> numerolla;

Pinot, jonot, yleisemmin sekvenssit: kokoelma peräkkäisiä alkioita (lineaarinen järjestys) Yleisempi tilanne: alkioiden hierarkia

Mikä yhteyssuhde on?

Rajapinta (interface)

Metodien tekeminen Javalla

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

811312A Tietorakenteet ja algoritmit, , Harjoitus 5, Ratkaisu

Ohjelmassa henkilön etunimi ja sukunimi luetaan kahteen muuttujaan seuraavasti:

16. Javan omat luokat 16.1

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

A TIETORAKENTEET JA ALGORITMIT

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Tietorakenneluokkia 2: HashMap, TreeMap

AVL-puut. eräs tapa tasapainottaa binäärihakupuu siten, että korkeus on O(log n) kun puussa on n avainta

1.1 Pino (stack) Koodiluonnos. Graafinen esitys ...

14. Poikkeukset 14.1

Rinnakkaisohjelmointi kurssi. Opintopiiri työskentelyn raportti

3. Hakupuut. B-puu on hakupuun laji, joka sopii mm. tietokantasovelluksiin, joissa rakenne on talletettu kiintolevylle eikä keskusmuistiin.

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

public static void main (String [] args)

List-luokan soveltamista. Listaan lisääminen Listan läpikäynti Listasta etsiminen Listan sisällön muuttaminen Listasta poistaminen Listan kopioiminen

1.1 Tavallinen binäärihakupuu

18. Abstraktit tietotyypit 18.1

811312A Tietorakenteet ja algoritmit, , Harjoitus 5, Ratkaisu

Tehtävä 1. Tehtävä 2. Arvosteluperusteet Koherentti selitys Koherentti esimerkki

Sisällys. 18. Abstraktit tietotyypit. Johdanto. Johdanto

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Java kahdessa tunnissa. Jyry Suvilehto

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Ohjelmointi 2, välikoe

Ohjelmointityö 3. Mikko Laamanen

YHTEYSSUHDE (assosiation)

Hakemistojen sisällöt säilötään linkitetyille listalle.

14. Poikkeukset 14.1

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

v 1 v 2 v 3 v 4 d lapsisolmua d 1 avainta lapsen v i alipuun avaimet k i 1 ja k i k 0 =, k d = Sisäsolmuissa vähint. yksi avain vähint.

811312A Tietorakenteet ja algoritmit V Hash-taulukot ja binääriset etsintäpuut

Ohjelmointityö 65 Tekstinmuotoilu ohjelma. Dokumentaatio. Aki Heikkinen (155394)

Koe ma 1.3 klo salissa A111, koeaika kuten tavallista 2h 30min

Tietorakenteet. JAVA-OHJELMOINTI Osa 5: Tietorakenteita. Sisällys. Merkkijonot (String) Luokka String. Metodeja (public)

58131 Tietorakenteet (kevät 2008) 1. kurssikoe, ratkaisuja

Tietorakenteet, laskuharjoitus 3, ratkaisuja

Kääreluokat (oppikirjan luku 9.4) (Wrapper-classes)

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

1.3Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä

Java-kielen perusteita

Vertailulauseet. Ehtolausekkeet. Vertailulauseet. Vertailulauseet. if-lauseke. if-lauseke. Javan perusteet 2004

A TIETORAKENTEET JA ALGORITMIT KORVAAVAT HARJOITUSTEHTÄVÄT 3, DEADLINE KLO 12:00

on ohjelmoijan itse tekemä tietotyyppi, joka kuvaa käsitettä

KOHDELUOKAN MÄÄRITTELY

Lista luokan sisällä

58131 Tietorakenteet ja algoritmit (kevät 2016) Ensimmäinen välikoe, malliratkaisut

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely

Sisältö. 22. Taulukot. Yleistä. Yleistä

Javan perusteita. Janne Käki

Pino S on abstrakti tietotyyppi, jolla on ainakin perusmetodit:

Tietorakenteet, laskuharjoitus 7, ratkaisuja

Sisältö Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 26.2

Sisältö. 2. Taulukot. Yleistä. Yleistä

Algoritmit 2. Luento 6 To Timo Männikkö

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Tietokannat II -kurssin harjoitustyö

Ohjelmointi 1 / 2009 syksy Tentti / 18.12

4. Luokan testaus ja käyttö olion kautta 4.1

lähtokohta: kahden O(h) korkuisen keon yhdistäminen uudella juurella vie O(h) operaatiota vrt. RemoveMinElem() keossa

Java-kielen perusteita

Taulukot. Taulukon määrittely ja käyttö. Taulukko metodin parametrina. Taulukon sisällön kopiointi toiseen taulukkoon. Taulukon lajittelu

9. Periytyminen Javassa 9.1

Linkitetystä listasta perittyä omaa listaa käytetään muun muassa viestiin liittyvien vastausten säilömiseen.

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

1. Omat operaatiot 1.1

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

Kierros 4: Binäärihakupuut

A) on käytännöllinen ohjelmointitekniikka. = laajennetaan aikaisemmin tehtyjä luokkia (uudelleenkäytettävyys)

20. Javan omat luokat 20.1

Metodit Arvotyyppi. Metodit Arvotyyppi. Metodit Parametrit. Metodit Parametrit. Metodit Kuormittaminen. Metodit Kuormittaminen. Javan perusteet

Ohjelmoinnin perusteet, kurssikoe

Sisällys. 20. Javan omat luokat. Java API. Pakkaukset. java\lang

CS-A1140 Tietorakenteet ja algoritmit

Algoritmit 1. Luento 6 Ke Timo Männikkö

Transkriptio:

Tietorakenteet ja algoritmit II Loppuraportti, ryhmä 7 Turun Yliopisto Informaatioteknologian laitos Kevät 2008 Jonne Pohjankukka, jjepoh@utu.fi, 73116 Simo Savonen, sipesa@utu.fi, 56572 Jyri Lehtonen, jkoleh@utu.fi, 72039

Sisällysluettelo 1. Suunnitelma...1 1.1. Tehtävän kuvaus ja analysointi...1 1.2. Ratkaisuperiaate...1 1.3. Ohjelman osien kuvaaminen...1 1.3.1. interface Tree...1 1.3.2. class BinarySearchTree implements Tree...2 1.3.3. class AVLTree implements Tree...3 1.3.4. class BinaryNode...5 1.3.5. class AVLNode...5 1.3.6. class TestTree...5 1.3.7. Alkuperäisen suunnitelman UML luokkakaavio...6 1.3.8. Toteutetun suunnitelman UML luokkakaavio...7 1.3.9. Työnjako...8 2. Toteutus...8 3. Testaus...9 3.1. data1ht.txt, 10.000 hakua ja maksimin poistoa...9 3.2. data2ht.txt, 1.000.000 hakua ja maksimin poistoa...10 3.3. data1ht4k.txt järjestetty, 4000 hakua ja maksimin poistoa...11 A. Käyttöohje...12 B. Koodilistaukset...13

1. Suunnitelma 1.1. Tehtävän kuvaus ja analysointi Ryhmälle 7 annettiin tehtäväksi verrata AVL-puun tehokkuutta tavalliseen binääripuuhun. Puut tuli toteuttaa Java-kielellä mahdollisimman elegantisti. Puiden metodien aikakompleksisuuksien pitäisi olla yhteneviä luentomonisteessa mainittuihin. Tehtävä tähtää havainnollistamaan mikä tekee AVL-puista parempia kuin binääripuut. Asia on helppo ymmärtää paperilla, haasteeksi nouseekin lähinnä asian toteaminen käytännön ohjelmakoodilla. Ryhmässä on kolme jäsentä, joten työ on luontevaa jakaa kolmeen osaan, tai luokkaan, joista kukin jäsen ohjelmoi yhden. 1.2. Ratkaisuperiaate Molempien puiden toteuttavat ohjelmaluokat tulisi sisältää samat julkiset metodit, jotta puiden vertailu olisi mahdollista. Tämä on kätevä toteuttaa yhteisellä julkisella rajapinnalla Tree. Luokkien muut metodit (rotaatiot, ym. apumetodit) ovat yksityisiä. Puiden käyttämät solmut sisältävät paljon yhteisiä piirteitä, joten tehdään luokka BinaryNode, jonka luokka AVLNode perii, lisäten siihen tiedon solmun korkeudesta. Sijoitetaan kukin luokka omaan tiedostoonsa, jotta työnjako helpottuu. Jätetään käyttämättä sisäluokkia. Jos tietoa halutaan kapseloida, määritellään luokat jakamaan yhteinen paketti. Puiden testaamista varten tehdään testiluokka, joka lukee tekstitiedostoa ja lisää puihin alkioita, mittaa operaatioihin käytetyn ajan erittäin tarkasti, sekä tulostaa yhteenvedon puun operaatioiden suoritusnopeuksista. 1.3. Ohjelman osien kuvaaminen 1.3.1. interface Tree Rajapintaan määritellään molempien puiden julkisten metodien signatuurit: public void add(comparable object); public void delete(comparable object); public Comparable find(comparable object); public Comparable min(); public Comparable max(); Jätetään toteuttamatta metodit size(), clear()rajataksemme harjoitustyötä. 1

1.3.2. class BinarySearchTree implements Tree Tasaisesti täyttyneen puun metodien kompleksisuus on yleisesti O(h) = O(lg n), mutta pahimmassa tapauksessa on O(h) = O(n) private BinaryNode root; // puun juuri Lisää alkion puuhun. Kompleksisuus O(h) = O(lg n), h on puun korkeus. public void add(comparable object); Poistaa alkion puusta. Kompleksisuus O(h) = O(lg n), h on puun korkeus. Seuraajan etsimisen kompleksisuus. public void delete(comparable object); Etsii alkiota puusta, palauttaa löydetyn alkion. Kompleksisuus O(h) = O(lg n), h on puun korkeus. Sekä iteratiivisen, että rekursiivisen on O(h). public Comparable find(comparable object); Palauttaa puun pienimmän alkion. Alkion vertailu compareto() avulla. Kompleksisuus O(h) = O(lg n), h on puun korkeus. public Comparable min(); Palauttaa puun suurimman alkion. Alkion vertailu compareto() avulla. Kompleksisuus O(h) = O(lg n), h on puun korkeus. public Comparable max(); Palauttaa solmun seuraajan. Kompleksisuus O(h) = O(lg n), h on puun korkeus. Kuljetaan polkua joko ylös tai alas, polun pituuden yläraja on h. private BinaryNode successor(binarynode); 2

1.3.3. class AVLTree implements Tree private AVLNode root; // puun juuri Lisää alkion puuhun. Kompleksisuus O(h) = O(lg n), h on puun korkeus. Korkeuksien päivityksen ja uudelleenjärjestämisen kompleksisuus on O(lg n). public void add(comparable object); Poistaa alkion puusta. Kompleksisuus O(h) = O(lg n), h on puun korkeus. Korkeuksien päivityksen ja uudelleenjärjestämisen kompleksisuus on O(lg n). public void delete(comparable object); Etsii alkiota puusta, palauttaa löydetyn alkion. Kompleksisuus O(h) = O(lg n), h on puun korkeus. public Comparable find(comparable object); Palauttaa puun pienimmän alkion. Alkion vertailu compareto() avulla. Kompleksisuus O(h) = O(lg n), h on puun korkeus. public Comparable min(); Palauttaa puun suurimman alkion. Alkion vertailu compareto() avulla. Kompleksisuus O(h) = O(lg n), h on puun korkeus. public Comparable max(); Palauttaa solmun seuraajan. Kompleksisuus O(h) = O(lg n), h on puun korkeus. private AVLNode successor(avlnode); 3

Rotaatio vasemmalle. Kompleksisuus Ө(1). private AVLNode leftrotate(avlnode); Rotaatio oikealle. Kompleksisuus Ө(1). private AVLNode rightrotate(avlnode); Kaksoisrotaatio vasemmalla alipuulla. Kompleksisuus Ө(1). private AVLNode doublerotateleft(avlnode); Kaksoisrotaatio oikealla alipuulla. Kompleksisuus Ө(1). private AVLNode doublerotateright(avlnode); 4

1.3.4. class BinaryNode private Comparable key; // solmun sisältämä satelliittidata private BinaryNode left; // vasen lapsisolmu private BinaryNode right; // oikea private BinaryNode parent; // isäsolmu public Comparable getkey(); public BinaryNode getparent(); public BinaryNode getleftchild(); public BinaryNode getrightchild(); public void setleftchild(binarynode); public void setrightchild(binarynode); public void setparent(binarynode); public void setkey(comparable); 1.3.5. class AVLNode AVLNode-luokassa on samat metodit ja piirteet(avl-tyyppisinä) kuin BinaryNode-luokallakin, sekä lisäksi seuraavat lisäykset : private int height; // solmun korkeus public int getheight(); public void setheight(int); 1.3.6. class TestTree TestTree luokassa luetaan testiainestoa ja luodaan IntStringPair-olioita, sijoitetaan ne puihin, tehdään hakuja ja poistoja sekä vertaillaan operaatioiden suoritusaikoja. 5

1.3.7. Alkuperäisen suunnitelman UML luokkakaavio TestClass +main(string): void -BinaryNode root BinarySearchTree +add(comparable): void +delete(comparable): void +min(): Comparable +max(): Comparable +find(comparable): Comparable -successor(binarynode): BinaryNode -predecessor(binarynode): BinaryNode <<interface>> Tree +add(comparable): void +delete(comparable): void +min(comparable): void +max(comparable): void +find(comparable): Comparable -AVLNode root AVLTree +add(comparable): void +delete(comparable): void +min(): Comparable +max(): Comparable +find(comparable): Comparable -leftrotate(avlnode): void -rightrotate(avlnode): void -successor(avlnode): AVLNode -predecessor(avlnode): AVLNode -doublerotateleft(avlnode): void -doublerotateright(avlnode): void BinaryNode #Comparable key #BinaryNode left #BinaryNode right #BinaryNode parent +getkey(): Comparable +getleftchild(): BinaryNode +setleftchild(binarynode): void +getrightchild(): BinaryNode +setrightchild(binarynode): void +getparent(): BinaryNode +setparent(binarynode): void -int height AVLNode +getheight(): int +setheight(int): void +increase(): void 6

1.3.8. Toteutetun suunnitelman UML luokkakaavio -BinaryNode root IntStringPair +Integer key +String value +compareto(object): int +equals(object): boolean +tostring(): String BinarySearchTree +add(comparable): void +delete(comparable): void +min(): Comparable +max(): Comparable +find(comparable): Comparable +isempty(): boolean -dataat(binarynode): Comparable -findmin(binarynode): BinaryNode -findmax(binarynode): BinaryNode -search(comparable, BinaryNode): Comparable -insert(comparable, BinaryNode): BinaryNode -remove(comparable, BinaryNode): BinaryNode -successor(binarynode): BinaryNode TestTree +main(string[]): void -testtree(int): void -testtreemap(): void -choosetestdata(): String -howmanytests(): int -howmanyrows(): int <<interface>> Tree +add(comparable): void +delete(comparable): void +find(comparable): Comparable +min(): void +max(): void -AVLNode root AVLTree +add(comparable): void +delete(comparable): void +min(): Comparable +max(): Comparable +find(comparable): Comparable -add(comparable, AVLNode, AVLNode): AVLNode -delete(comparable, AVLNode): AVLNode -min(avlnode): AVLNode -max(avlnode): AVLNode -find(comparable, AVLNode): Comparable -findnode(comparable, AVLNode): AVLNode -leftrotate(avlnode): AVLNode -rightrotate(avlnode): AVLNode -successor(avlnode): AVLNode -doublerotateleft(avlnode): AVLNode -doublerotateright(avlnode): AVLNode BinaryNode -BinaryNode left -BinaryNode right -BinaryNode parent -Comparable key +getkey(): Comparable +setkey(comparable): void +getleftchild(): BinaryNode +setleftchild(binarynode): void +getrightchild(): BinaryNode +setrightchild(binarynode): void +getparent(): BinaryNode +setparent(binarynode): void AVLNode -int height -AVLNode left -AVLNode right -AVLNode parent -Comparable key +getheight(): int +setheight(int): void +getkey(): Comparable +setkey(comparable): void +getleftchild(): AVLNode +setleftchild(avlnode): void +getrightchild(): AVLNode +setrightchild(avlnode): void +getparent(): AVLNode +setparent(avlnode): void 7

1.3.9. Työnjako Ryhmässä on kolme jäsentä, ja toteutettavia luokkakokonaisuuksia on samoin kolme. Ohjelmointityöt jaetaan seuraavasti: BinarySearchTree AVLTree TestClass Jyri Lehtonen Jonne Pohjankukka Simo Savonen Puiden käyttämät solmuluokat ohjelmoitiin yhdessä. 2. Toteutus Suunnitelmasta poikettiin seuraavasti: Koodauksen helpottamiseksi, AVLNode ei peri BinaryNode luokkaa. Esittelytilaisuudessa mainittu Tree on yliluokka -toteutustapa ei lopulta vaikuttanut hyvältä. Olisimme joka tapauksessa joutuneet ylikirjoittamaan metodit perivissä luokissa. Puihin lisättävä Comparable rajapinnan toteuttava olio on IntStringPair olio, joka sisältää kokonaisluvun ja merkkijonon. TestClass -luokasta tuli TreeTest luokka, joka testaa BinarySearchTree:n ja AVLTree:n lisäksi java.util.treemap punamustaa puuta, verrataksemme tuloksia. Testaamme puihin lisäämistä, niistä hakemista ja poistamista. Toteutuksessa lisättiin luokka IntStringPair : class IntStringPair implemets Comparable IntStringPair-luokasta luodaan olioita, joiden attribuuteiksi asetetaan testiaineiston dataa. IntStringPair-luokka toteuttaa rajapinnan Comparable. public Integer key; public String value; public int compareto(object o); public boolean equals(object o); public String tostring(); 8

3. Testaus TreeTest luokka kysyy käyttäjältä testattavan puun, testiaineiston ja montako solmua puusta etsitään ja poistetaan. Käytimme testiaineistoina annettuja data1ht.txt ja data2ht.txt tiedostoja, jotka sisälsivät kokonaisluku-merkkijono pareja. Tämän lisäksi järjestimme data1ht.txt kasvavaan numerojärjestykseen, ja otimme sen ensimmäiset 4000 riviä tiedostoon data1ht4k.txt. Tällä aineistoilla saimme näkyville BinarySearchTree:n heikkouden järjestetyn aineiston suhteen. Add on aineiston rivien lisäyksen viemä aika millisekunteina. Find kuvaa aikaa mikä kului kun puusta etsittiin n. solmua. Delete kuvaa aikaa mikä kului puun maksimin poistamiseen n. kertaa. 3.1. data1ht.txt, 10.000 hakua ja maksimin poistoa 80 70 BinarySearchTree AVLTree TreeMap 60 50 ms 40 30 20 10 0 Add Find Delete BinarySearchTree pärjää hyvin tasapainoitettujen puiden rinnalla. AVLTree on hieman nopeampi hauissa, joka selittynee tasapainoituksilla. Sen sijaan lisääminen ja poistaminen AVLTree:hen on hitaampaa kuin BinarySearchTree:hen. 9

3.2. data2ht.txt, 1.000.000 hakua ja maksimin poistoa 14000 12000 BinarySearchTree AVLTree TreeMap 10000 8000 ms 6000 4000 2000 0 Add Find Delete BinarySearchTree on nopeampi lisättäessä ja poistettaessa puusta. AVLTree voittaa vain hauissa. 10

3.3. data1ht4k.txt järjestetty, 4000 hakua ja maksimin poistoa 450 400 350 BinarySearchTree AVLTree TreeMap 300 ms 250 200 150 100 50 0 Add Find Delete Käytettäessä valmiiksi suuruusjärjestyksessä olevaa aineistoa, BinarySearchTree:n suurin heikkous käy ilmi. AVLTree:n tasapainoitusten edut ovat selvät. 11

A. Käyttöohje Ajaessasi java tulkkia, anna sille lisää muistia Xmx200M kytkimellä, jotta testiajot eivät kaadu. Oletetaan, että ohjelmakoodipaketti on purettu kansioon C:\TRAK2 Puiden testaus onnistuu TreeTest luokalla. C:\TRAK2\javac.java C:\TRAK2\java Xmx200M TreeTest TreeTest tallentaa testitulokset tiedostoihin. 12

B. Koodilistaukset Tree.java @(#)Tree.java @author Jonne Pohjankukka @version 1.00 2008/3/6 public interface Tree public void add(comparable key); public void delete(comparable key); public Comparable min(); public Comparable max(); public Comparable find(comparable key); BinaryNode.java BinaryNode on binäärisen hakupuun solmu. @author Simo Savonen @version 1.0 (13.2.2008) public class BinaryNode protected Comparable key; // solmun satelliittidata protected BinaryNode left; // vasen lapsi protected BinaryNode right; // oikea lapsi protected BinaryNode parent; // solmun isä Konstruktori. Viittaukset lapsisolmuihin ja isäsolmuun asetetaan vasta lisättäessä solmu puuhun. @param data satelliittidata, toteuttaa rajapinnan Comparable public BinaryNode(Comparable data) key = data; left = null; right = null; parent = null; public Comparable getkey() return key; public BinaryNode getleftchild() return left; public BinaryNode getrightchild() return right; public BinaryNode getparent() return parent; public void setkey(comparable k) key = k; public void setleftchild(binarynode node) left = node; public void setrightchild(binarynode node) right = node; public void setparent(binarynode node) parent = node; 13

BinarySearchTree.java Luokka mallintaa binäärisen hakupuun toimintoja. Binäärinen hakupuu on tietynlainen binääripuu. Operaatiot: - Haku ( find() -> search() ) - Lisäys ( add() -> insert() ) - Poisto ( delete() -> remove() ) - Minimi ( min() -> findmin() ) - Maksimi ( max() -> find max() ) - Tyhjyys ( isempty() ) - Seuraaja ( findsuccessor -> successor() ) @author Jyri Lehtonen @version 1.3 (12.3.2008) public class BinarySearchTree implements Tree ILMENTYMÄMUUTTUJAT //Viittaa puun juureen, jos null niin puu on tyhjä. private BinaryNode root; KONSTRUKTORI public BinarySearchTree() this.root = null; PROSEDUURIT //Lisää alkion puuhun (kutsumalla apumetodia insert()) public void add(comparable x) root = insert(x, root); //Poistaa alkion puusta (kutsumalla apumetodia remove()) public void delete(comparable x) remove(x,root); //Etsii puun pienimmän alkion (kutsumalla apumetodia (findmin()) public Comparable min() return dataat(findmin(root)); //Etsii puun suurimman alkio (kutsumalla apumetodia findmax()) public Comparable max() return dataat(findmax(root)); //Etsii alkion puusta (kutsumalla apumetodia search()) public Comparable find(comparable x) return search(x, root); //Tarkistaa onko puu tyhjä public boolean isempty() return root == null; 14

FUNKTIOT Apumetodi, joka auttaa alkion datan hankinnassa. @.pre = on saatava parametri @param t parametrinä saatu alkio @.post palauttaa alkion datan tai null jos t on null. private Comparable dataat(binarynode t) if (t == null) return null; else return t.key; Apumetodi, joka etsii pienimmän alkion puusta. Idea: Lähdetään liikkeelle juuresta, ja pienin alkio on puun kaikista vasemmanpuoleisin alkio. Edetään niin kauan, kunnes alkiolla ei ole enää lasta vasemmalla puolella, tämä alkio on silloin pienin ja se palautetaan. @.pre = on saatava parametri @param x parametrina saatu alkio (puun juuri) @.post = palauttaa pienimmän alkion arvon puusta private BinaryNode findmin(binarynode x) if (x== null) return null; while (x.left!= null) x = x.left; return x; Apumetodi, joka etsii suurimman alkion puusta. Idea: Lähdetään liikkeelle juuresta, ja suurin alkio on puun kaikista oikeanpuoleisin alkio. Edetään niin kauan, kunnes alkiolla ei ole enää lasta oikealla puolella, tämä alkio on silloin suurin ja se palautetaan. @.pre = on saatava parametri @param x parametrina saatu alkio (puun juuri) @.post = palauttaa suurimman alkion arvon puusta private BinaryNode findmax(binarynode x) if (x== null) return null; while (x.right!= null) x = x.right; return x; 15

Toteuttaa haun puuhun. Jos verrattava on null, ilmoitetaan siitä palauttamalla null. Jos verrattava on jotain muuta, verrataan metodin parametrejä keskenään (x ja t). Jos vertailun tulos on -1 (aka < 0) asetetaan seuraavaan rekursiiviseen kutsuun haku vasempaan lapseen. Jos vertailun tulos on 1 (aka > 0), asetetaan seuraavaan rekursiiviseen kutsuun haku oikeaan lapseen. Jos vertailun tulos on 0, (aka == 0), on etsitty alkio löydetty, joten palautetaan se. @.pre = (x!= null) && (t!= null) @param x on se alkio, jota puusta etsitään. @param t on se alkio, joka on puun juurena. @.post = palauttaa alkion, jota on etsitty. private Comparable search(comparable x, BinaryNode t) if (x == null) return null; else if ( x.compareto(t.key) < 0 ) return search(x, t.left); if ( x.compareto(t.key) > 0 ) return search(x, t.right); if ( x.compareto(t.key) == 0 ) return x; return null; Toteuttaa lisäyksen puuhun. Jos puu on tyhjä (null), luodaan uusi alkio (ali)puun juureen. Jotta lisäys löytää oikeaan paikkaan puussa, on verrattava puun alkioita haun tapaisesti kunnes oikea pakka on löytynyt. compareto arvo -1 -> Edetään vasemmalle compareto arvo +1 -> Edetään oikealle compareto arvo 0 -> Duplikaatti, ei tehdä mitään. @.pre = lisättävä alio on annettava @param x lisättävä alkio @param t puun juuri @return uusi juuri @.post = uusi alkio on lisätty puuhun private BinaryNode insert(comparable x, BinaryNode node) if (node==null) node=new BinaryNode(x); node.setparent(node); else if (x.compareto(node.key) < 0) node.left = insert(x, node.left); if (x.compareto(node.key) > 0) node.right= insert(x, node.right); return node; 16

Toteuttaa poiston puusta. Jos alkiota ei löydetä, ei tehdä mitään. Tämän jälkeen on käsiteltävä binäärisen hakupuun poiston erilaiset tapaukset, tapaus 1: solmulla ei ole lapsia (null & null) tapaus 2: solmulla on yksi lapsi (null & not null) tapaus 3: solmulla on kaksi lasta (not null & not null) (talletetaan seuraajan avainarvo ja data ja poistetaan seuraaja alkio. Kopioidaan seuraajan tiedot poistettavan alkion päälle) @param x poistettava solmu @param t puun juuri @return tapauskohtainen private BinaryNode remove(comparable x, BinaryNode t) BinaryNode y; if (t == null) return t; else //Etsitään vasemmalta if(x.compareto(t.getkey()) < 0) t.setleftchild(remove(x, t.getleftchild())); //Etsitään oikealta if(x.compareto(t.getkey()) > 0) t.setrightchild(remove(x, t.getrightchild())); //Löytyi, käsitellään tapaukset if(x.compareto(t.getkey()) == 0) if(t.getleftchild() == null & t.getrightchild() == null) return null; if(t.getleftchild()!= null & t.getrightchild() == null) t.getleftchild().setparent(t.getparent()); t = t.getleftchild(); return t; if(t.getleftchild() == null & t.getrightchild()!= null) t.getrightchild().setparent(t.getparent()); t = t.getrightchild(); return t; if(t.getleftchild()!= null & t.getrightchild()!= null) Comparable succkey = successor(t).getkey(); t = remove(succkey, t); t.setkey(succkey); //return t; return t; 17

Etsii annetun alkion seuraajan. Jos oikea alipuu ei ole tyhjä, niin x:n seuraaja on oikean alipuun pienin alkio. Oikealla on x:ää suuremmat, otetaan niistä pienin. Jos oikea alipuu on tyhjä, niin x:n seuraaja etsitään kipuamalla ylös puuta, kunnes löydetään ensimmäinen solmu y, jonka vasempaan alipuuhun x kuuluu. Se on ensimmäinen alkio, joka on x:ää suurempi. public BinaryNode successor(binarynode x) if (x.right!= null) return findmin(x.right); BinaryNode y = x.parent; while ((y!= null) && (x.equals(y.right))) x = y; y = y.parent; return y; MAIN METODI PUUN TOIMINNAN TESTAUKSEEN / public static void main(string [] args) BinarySearchTree t = new BinarySearchTree(); t.add(10); // 10 t.add(5); // 5 15 t.add(15); // 3 7 12 18 t.add(7); // t.add(12); t.add(3); t.add(18); System.out.println("Puun Juuri: " +t.root.getkey()); System.out.println("Juuren vasen lapsi: "+t.root.getleftchild().getkey()); System.out.println("Juuren oikea lapsi: "+t.root.getrightchild().getkey()); System.out.println("Puun minimi: " +t.min()); System.out.println("Puun maksimi: "+t.max()); System.out.println("Haku, haetaan 7: "+ t.find(7)); System.out.println("Poistetaan root! (oli 10, oltava 12 nyt)"); t.delete(t.root.getkey()); System.out.println("Haetaan uusi root: " +t.root.getkey()); System.out.println("Poistetaan 15 (yksi lapsi nyt)"); t.delete(15); 18

AVLNode.java AVLNode on AVL-puun tasapainoitettu solmu. @author Jonne Pohjankukka @version 2.0 2008/3/6 public class AVLNode //JÄSENMUUTTUJAT private int height; // solmun korkeus private AVLNode left; // vasen lapsi private AVLNode right; // oikea lapsi private AVLNode parent; // vanhempi private Comparable key; // solmun satelliittidata // KONSTRUKTORI @param data satelliittidata, toteuttaa rajapinnan Comparable. @post AVLNode konstruoitu public AVLNode(Comparable data) key = data; left = null; right = null; parent = null; height = 0; // solmu lisätään aina lehdeksi // FUNKTIOT public Comparable getkey() return key; public AVLNode getleftchild() return left; public AVLNode getrightchild() return right; public AVLNode getparent() return parent; public int getheight() return height; // METODIT public void setkey(comparable newkey) key = newkey; public void setleftchild(avlnode node) left = node; public void setrightchild(avlnode node) right = node; public void setparent(avlnode node) parent = node; public void setheight(int h) height = h; //class AVLNode 19

AVLTree.java @(#)AVLTree.java @author Jonne Pohjankukka @version 2.00 2008/3/6 public class AVLTree implements Tree // JÄSENMUUTTUJA AVL-puun juuri private AVLNode root; AVL-puun konstruktori public AVLTree() root = null; julkinen metodi rajapinnalle, joka palauttaa AVL-puun minimin. @param AVLNode Root @post minimi palautettu public Comparable min() return min(root).getkey(); julkinen metodi rajapinnalle, joka palauttaa AVL-puun maksimin. @param AVLNode Root @post minimi palautettu public Comparable max() AVLNode result = max(root); if(result!= null) return result.getkey(); else return null; julkinen metodi rajapinnalle, joka etsii solmun AVL-puusta. @param Comparable key @pre key!= null @post etsitty solmu palautettu public Comparable find(comparable key) return find(key, root); julkinen metodi rajapinnalle, joka lisää solmun AVL-puuhun. @param Comparable key @pre key!= null @post solmu lisätty public void add(comparable key) root = add(key, root, null); 20

julkinen metodi rajapinnalle, joka poistaa solmun AVL-puusta. @param Comparable key @pre key!= null @post solmu poistettu public void delete(comparable key) root = delete(key, root); Julkinen metodi, joka tulostaa puun solmujen avainarvot suuruusjärjestyksessä. @param AVLNode t @pre t!= null @post puu tulostettuna public void outputtree(avlnode node) if( node!= null ) outputtree( node.getleftchild() ); System.out.println( node.getkey() ); outputtree( node.getrightchild() ); privaatti metodi, joka palauttaa AVL-puun minimin. @param AVLNode Root @post minimi palautettu private AVLNode min(avlnode Root) if(root == null) return null; else AVLNode node = Root; while(node.getleftchild()!= null) node = node.getleftchild(); return node; privaatti metodi, joka palauttaa AVL-puun maksimin. @param AVLNode Root @post maksimi palautettu private AVLNode max(avlnode Root) if(root == null) return null; else AVLNode node = Root; while(node.getrightchild()!= null) node = node.getrightchild(); return node; 21

privaatti metodi, joka etsii parametrina annetun solmun. @param Comparable key @param AVLNode node @pre key!= null @post etsitty solmu palautettu private Comparable find(comparable key, AVLNode node) while(node!= null) if(key.compareto(node.getkey()) == -1) node = node.getleftchild(); else if(key.compareto(node.getkey()) == 1) node = node.getrightchild(); else // solmu löytyi return node.getkey(); return null; // kyseistä solmua ei ole puussa privaatti metodi, joka etsii parametrina annetun solmun. Huom. palauttaa AVLNode:n ei sen dataa. @param Comparable key @param AVLNode node @pre key!= null @post etsitty solmu palautettu private AVLNode findnode(comparable key, AVLNode node) while(node!= null) if(key.compareto(node.getkey()) == -1) node = node.getleftchild(); else if(key.compareto(node.getkey()) == 1) node = node.getrightchild(); else // solmu löytyi return node; return null; // kyseistä solmua ei ole puussa 22

privaatti metodi, joka poistaa solmun AVL-puusta. @param AVLNode node @param Comparable key @pre key!= null @post solmu poistettu private AVLNode delete(comparable key, AVLNode node) if(node == null) return null; if(key.compareto(node.getkey()) == 0) // SOLMU LÖYTYI if(node.getleftchild() == null & node.getrightchild() == null) return null; if(node.getleftchild()!= null & node.getrightchild() == null) node.getleftchild().setparent(node.getparent()); node = node.getleftchild(); return node; if(node.getleftchild() == null & node.getrightchild()!= null) node.getrightchild().setparent(node.getparent()); node = node.getrightchild(); return node; if(node.getleftchild()!= null & node.getrightchild()!= null) int korkennen = node.getheight(); Comparable successorkey = successor(node).getkey(); Comparable nodekey = node.getkey(); AVLNode nodeorig = node; node = delete(successorkey, node); int korkjälkeen = node.getheight(); if(korkennen!= korkjälkeen) node.setheight(maxkorkeus(node.getleftchild(), node.getrightchild()) + 1); nodeorig.setkey(successorkey); return node; if(key.compareto(node.getkey()) == -1) node.setleftchild(delete(key, node.getleftchild())); if(height(node.getrightchild())-height(node.getleftchild()) ==2) if((node.getrightchild()!= null & node.getrightchild().getrightchild()!= null) (node.getrightchild()!= null & node.getrightchild().getrightchild()!= null & node.getrightchild().getleftchild()!= null)) node = leftrotate(node); else node = doublerotateright(node); else if(key.compareto(node.getkey()) == 1) node.setrightchild(delete(key, node.getrightchild())); 23

if(height(node.getleftchild())-height(node.getrightchild()) == 2) if((node.getleftchild()!= null & node.getleftchild().getleftchild()!= null) (node.getleftchild()!= null & node.getleftchild().getleftchild()!= null & node.getleftchild().getrightchild()!= null)) node = rightrotate(node); else node = doublerotateleft(node); node.setheight(maxkorkeus(node.getleftchild(), node.getrightchild()) + 1); return node; privaatti metodi, joka lisää AVL-puuhun solmun. @param AVLNode node, parent @param Comparable key @pre key!= null @post solmu lisätty private AVLNode add(comparable key, AVLNode node, AVLNode parent) if(node == null) node = new AVLNode(key); node.setparent(parent); else if(key.compareto(node.getkey()) == -1) node.setleftchild(add(key, node.getleftchild(), node)); if(height(node.getleftchild())-height(node.getrightchild()) == 2) if(key.compareto(node.getleftchild().getkey()) == -1) node = rightrotate(node); else node = doublerotateleft(node); else if(key.compareto(node.getkey()) == 1) node.setrightchild(add(key, node.getrightchild(), node)); if(height(node.getrightchild())-height(node.getleftchild()) == 2) if(key.compareto(node.getrightchild().getkey()) == 1) node = leftrotate(node); else node = doublerotateright(node); node.setheight(maxkorkeus(node.getleftchild(), node.getrightchild()) + 1); return node; 24

apumetodi lisäykselle ja poistolle, joka palauttaa solmun korkeuden. @param AVLNode node @post korkeus palautettu private int height(avlnode node) return node == null? -1 : node.getheight(); palauttaa solmun lapsien suuremmman korkeuden. @param AVLNode leftc, rightc @pre leftc!= null & rightc!= null @post suurempi korkeus palautettu private int maxkorkeus(avlnode leftc, AVLNode rightc) int lefth, righth; if(leftc == null) lefth = -1; else lefth = leftc.getheight(); if(rightc == null) righth = -1; else righth = rightc.getheight(); return lefth > righth? lefth : righth; privaatti metodi, joka palauttaa solmun seuraajan. @param AVLNode node @pre node!= null @post seuraajasolmu palautettu private AVLNode successor(avlnode node) if(node.getrightchild()!= null) return min(node.getrightchild()); AVLNode nodey = node.getparent(); while(nodey!= null & node == node.getrightchild()) node = nodey; nodey = nodey.getparent(); return nodey; 25

Vasen rotaatio solmulla node. @param AVLNode node @pre node!= null @post rotaatio tehty private AVLNode leftrotate(avlnode node) AVLNode rightchild = node.getrightchild(); // solmun oikea lapsi node.setrightchild(rightchild.getleftchild()); // solmun oikeaksi lapseksi asetetaan oikean lapsen vasen lapsi rightchild.setparent(node.getparent()); // oikean lapsen vanhemmaksi entisen vanhemman vanhempi node.setparent(rightchild); // solmun vanhemmaksi asetetaan oikea lapsi rightchild.setleftchild(node); // oikean lapsen vasemmaksi lapseksi solmu // päivitetään solmujen korkeudet node.setheight(maxkorkeus(node.getleftchild(), node.getrightchild()) + 1); rightchild.setheight(maxkorkeus(rightchild.getleftchild(), rightchild.getrightchild()) + 1); return rightchild; // palautetaan oikea lapsi Oikea rotaatio solmulla node. @param AVLNode node @pre node!= null @post rotaatio tehty private AVLNode rightrotate(avlnode node) AVLNode leftchild = node.getleftchild(); // solmun vasen lapsi node.setleftchild(leftchild.getrightchild()); // solmun vasemmaksi lapseksi asetetaan vasemman lapsen oikea lapsi leftchild.setparent(node.getparent()); // vasemman lapsen vanhemmaksi entisen vanhemman vanhempi node.setparent(leftchild); // solmun vanhemmaksi asetetaan vasen lapsi leftchild.setrightchild(node); // vasemman lapsen oikeaksi lapseksi solmu // päivitetään solmujen korkeudet node.setheight(maxkorkeus(node.getleftchild(), node.getrightchild()) + 1); leftchild.setheight(maxkorkeus(leftchild.getleftchild(), leftchild.getrightchild()) + 1); return leftchild; // palautetaan vasen lapsi Kaksoisrotaatio Ensin tehdään rotaatio vasemmalle solmun vasemmalla lapsella ja sitten oikea rotaatio solmulla. @param AVLNode node @pre node!= null @post rotaatio tehty private AVLNode doublerotateleft(avlnode node) node.setleftchild(leftrotate(node.getleftchild())); return rightrotate(node); 26

Kaksoisrotaatio Ensin tehdään rotaatio oikealle solmun oikealla lapsella ja sitten vasen rotaatio solmulla. @param AVLNode node @pre node!= null @post rotaatio tehty private AVLNode doublerotateright(avlnode node) node.setrightchild(rightrotate(node.getrightchild())); return leftrotate(node); //class AVLTree IntStringPair.java IntStringPair on binääripuiden testaukseen käytettävä Comparable rajapinnan tot. luokka. @author Simo Savonen @version 1.1 (11.3.2008) public class IntStringPair implements Comparable public Integer key; public String value; public IntStringPair(Integer k, String v) key = k; value = v; public int compareto(object o) IntStringPair isp = (IntStringPair)o; return key.compareto(isp.key); public boolean equals(object o) IntStringPair isp = (IntStringPair)o; return key.equals(isp.key); public String tostring() return key + ", " + value; 27

TreeTest.java import java.io.; import java.util.; TreeTest testaa binääripuita. @author Simo Savonen @version 1.0 (10.3.2008) public class TreeTest Testaa Tree -rajapinnan toteuttavia binääripuita. private static void testtree(int choise) String file = choosetestdata(); int tests = howmanytests(); int rows = howmanyrows(); try FileWriter fstream = null; if(choise == 1) fstream = new FileWriter(tests + "_BinarySearchTree_" + file); else if(choise == 2) fstream = new FileWriter(tests + "_AVLTree_" + file); BufferedWriter out = new BufferedWriter(fstream); out.write("add\tfind\tdelete"); // otsikot sarakkeille out.newline(); Scanner scanner = null; for(int i = 1; i <= tests; i++) Tree tree = null; if(choise == 1) tree = new BinarySearchTree(); else if (choise == 2) tree = new AVLTree(); add scanner = new Scanner(new File(file)); long addstart = System.nanoTime(); // aloitetaan ajanotto while(scanner.hasnextint()) tree.add(new IntStringPair(scanner.nextInt(), scanner.next())); double addelapsed = (System.nanoTime() - addstart) / 1000000.0; // kesto System.out.println("Adding " + file + " took " + addelapsed + "ms."); scanner.close(); 28

find scanner = new Scanner(new File(file)); long findstart = System.nanoTime(); // aloitetaan ajanotto int j = 1; int laskuri = 0; while(scanner.hasnextint() & j <= rows) if(tree.find(new IntStringPair(scanner.nextInt(), scanner.next()))!= null) laskuri++; j++; double findelapsed = (System.nanoTime() - findstart) / 1000000.0; // kesto System.out.println("Found " + laskuri + " nodes from " + file + ", it took " + findelapsed + "ms."); scanner.close(); delete long deletestart = System.nanoTime(); // aloitetaan ajanotto int k = 1; while(k <= rows) tree.delete(tree.max()); k++; double deleteelapsed = (System.nanoTime() - deletestart) / 1000000.0; // kesto System.out.println("Deleting max() " + rows + " times from " + file + " took " + deleteelapsed + "ms."); kirjoitetaan tulokset tiedostoon out.write(addelapsed + "\t" + findelapsed + "\t" + deleteelapsed); out.newline(); tree = null; // for out.close(); catch(exception e) e.printstacktrace(); 29

Testaa java.util.treemap punamustaa binääripuuta. private static void testtreemap() String file = choosetestdata(); int tests = howmanytests(); int rows = howmanyrows(); try FileWriter fstream = new FileWriter(tests + "_TreeMap_" + file); BufferedWriter out = new BufferedWriter(fstream); out.write("add\tfind\tdelete"); // otsikot sarakkeille out.newline(); Scanner scanner = null; for(int i = 1; i <= tests; i++) TreeMap<Integer, String> tree = new TreeMap<Integer, String>(); add scanner = new Scanner(new File(file)); long addstart = System.nanoTime(); // aloitetaan ajanotto while(scanner.hasnextint()) tree.put(scanner.nextint(), scanner.next()); double addelapsed = (System.nanoTime() - addstart) / 1000000.0; // kesto System.out.println("Adding " + file + " took " + addelapsed + "ms."); scanner.close(); find scanner = new Scanner(new File(file)); long findstart = System.nanoTime(); // aloitetaan ajanotto int j = 1; int laskuri = 0; while(scanner.hasnextint() & j <= rows) if(tree.get(scanner.nextint())!= null) laskuri++; scanner.next(); j++; double findelapsed = (System.nanoTime() - findstart) / 1000000.0; // kesto System.out.println("Found " + laskuri + " nodes from " + file + ", it took " + findelapsed + "ms."); scanner.close(); 30

delete long deletestart = System.nanoTime(); // aloitetaan ajanotto int k = 1; while(k <= rows) try tree.remove(tree.lastkey()); catch(nosuchelementexception nse) // ei välitetä mahd. dublikaateista k++; double deleteelapsed = (System.nanoTime() - deletestart) / 1000000.0; // kesto System.out.println("Deleting lastkey() " + rows + " times from " + file + " took " + deleteelapsed + "ms."); kirjoitetaan tulokset tiedostoon out.write(addelapsed + "\t" + findelapsed + "\t" + deleteelapsed); out.newline(); tree = null; // for out.close(); catch(exception e) System.err.println("Error: " + e); public static void main(string[] args) System.out.println("\n"); System.out.println(" TreeTest "); System.out.println(" 1. BinarySearchTree "); System.out.println(" 2. AVLTree "); System.out.println(" 3. java.util.treemap "); System.out.println(""); System.out.print("\nChoose 1, 2 or 3. 0 for exit: "); try BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int choise = Integer.parseInt(br.readLine().trim()); switch(choise) case 0: System.exit(0); case 1: testtree(choise); break; case 2: testtree(choise); break; case 3: testtreemap(); break; default: System.out.println("Invalid choise entered, exiting program."); break; catch(ioexception e) System.err.println("Exception: " + e); 31

private static String choosetestdata() System.out.println("\n"); System.out.println(" How many nodes? "); System.out.println(" 1. data1ht.txt (10k) "); System.out.println(" 2. data2ht.txt (1000k) "); System.out.println(" 3. input file name "); System.out.println(""); System.out.print("\nChoose 1, 2 or 3. 0 for exit: "); try BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); int choise = Integer.parseInt(br.readLine().trim()); switch(choise) case 0: System.exit(0); case 1: return new String("data1HT.txt"); case 2: return new String("data2HT.txt"); case 3: System.out.print("\nInput file name: "); return new String(br.readLine().trim()); default: return null; catch(ioexception e) System.err.println("Exception: " + e); return null; private static int howmanytests() System.out.print("\nHow many test runs? Enter number: "); try BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); return Integer.parseInt(br.readLine().trim()); catch(ioexception e) System.err.println("Exception: " + e); return 0; private static int howmanyrows() System.out.print("\nHow many rows to find/delete? Enter number: "); try BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); return Integer.parseInt(br.readLine().trim()); catch(ioexception e) System.err.println("Exception: " + e); return 0; 32