Universität der Bundeswehr Fakultät für Informatik – Institut 2 Priv.-Doz. Dr. Lothar Schmitz FT 2006 Übungsblatt 5 Lösungsvorschlag Objektorientierte Programmierung 22. 05. 2006 Lösung 9 (SMS-Eingabe am Handy mit Tries) import java.util.*; /** * Abstrakte Oberklasse der in T9 fuer Woerterbuecher * verwendeten Tries; legt Schnittstelle fest und stellt * die Hilfsmethode "tasteZu" bereit. */ public abstract class T9Trie { /** * Konversionsmethode: liefert Tastennummer zu Zeichen * * @param z das Zeichen * @return die Nummer der Taste, auf der z liegt */ static public int tasteZu (char z) { String belegung = "ABC " + // Taste 2 "DEF " + // Taste 3 "GHI " + // Taste 4 "JKL " + // Taste 5 "MNO " + // Taste 6 "PQRS" + // Taste 7 "TUV " + // Taste 8 "WXYZ"; // Taste 9 return belegung.indexOf(z) / 4 + 2; } public String prefix (int tabs) { String erg = ""; for (int i = 0; i < tabs; i++) erg += " "; return erg; } public abstract String toString(int tabs); public String toString() { return toString(0); } /** 1 * Mit Tastenfolge vertraegliche Woerter bestimmen. * * @param tastenfolge die Tastenfolge als int-Array * @param ab Index, ab dem Tastenfolge noch zu bearbeiten ist. * @return Liste der vertraeglichen Woerter */ public abstract List suchen (int[] tastenfolge, int ab); /** * Neues Wort in Woerterbuch eintragen. * * @param wort das einzutragende Wort als String * @param ab Index, ab dem wort noch zu bearbeiten ist. * @return Trie, der zusaetzlich wort enthaelt */ public abstract T9Trie eintragen (String wort, int ab); /** * Iterator zu Trie erstellen und zurueckgeben. */ public abstract Iterator iterator (); } ////////////////////////////////////////////////////////////////// import java.util.*; /** * Leere Tries - statt null verwenden! */ public class EmptyTrie extends T9Trie { /** * Konstante, die das einzige EmptyTrie enthaelt und * oeffentlich bereitstellt. */ public static final EmptyTrie LEER = new EmptyTrie(); /** * Konstruktor fuer EmptyTrie-Objekte. * Privat, um Singleton-Eigenschaft zu * gewaehrleisten! */ private EmptyTrie () {} /** * Mit Tastenfolge vertraegliche Woerter bestimmen. * * @param tastenfolge die Tastenfolge als int-Array * @param ab Index, ab dem Tastenfolge noch zu bearbeiten ist. * @return Liste der vertraeglichen Woerter */ public List suchen (int[] tastenfolge, int ab) { return new LinkedList(); 2 } /** * Neues Wort in Woerterbuch eintragen. * * @param wort das einzutragende Wort als String * @param ab Index, ab dem wort noch zu bearbeiten ist. * @return Trie, der zusaetzlich wort enthaelt */ public T9Trie eintragen (String wort, int ab) { T9Trie neu = new Trie(); neu = neu.eintragen (wort, ab); return neu; } /** * Iterator zu leerem Trie erstellen und zurueckgeben. */ public Iterator iterator () { return new EmptyTrieIterator(); } public String toString(int tabs) { return "[ emptyTrie ]"; } } ////////////////////////////////////////////////////////////////// import java.util.*; /** * Klasse der inneren Knoten eines Tries. */ public class Trie extends T9Trie { private List wortliste; private T9Trie[] sohn; //sohn[i] wird ueber Taste i+2 erreicht /** * getter fuer wortliste */ public List getWortliste() { return wortliste; } /** * getter fuer sohn */ public T9Trie[] getSohn() { return sohn; } 3 /** * Konstruktor fuer Trie-Objekte. * Belegt alle Attribute entsprechend der * Sicherheitsanforderung. */ public Trie() { wortliste = new LinkedList(); sohn = new T9Trie[8]; for (int i = 0; i < 8; i++) sohn[i] = EmptyTrie.LEER; } /** * Mit Tastenfolge vertraegliche Woerter bestimmen. * * @param tastenfolge die Tastenfolge als int-Array * @param ab Index, ab dem Tastenfolge noch zu bearbeiten ist. * @return Liste der vertraeglichen Woerter */ public List suchen (int[] tastenfolge, int ab) { if (ab == tastenfolge.length) return wortliste; return sohn[tastenfolge[ab]-2].suchen(tastenfolge,ab+1); } /** * Neues Wort in Woerterbuch eintragen. * * @param wort das einzutragende Wort als String * @param ab Index, ab dem wort noch zu bearbeiten ist. * @return Trie, der zusaetzlich wort enthaelt */ public T9Trie eintragen (String wort, int ab) { if (ab == wort.length()) { wortliste.add(wort); return this; } int i = tasteZu(wort.charAt(ab))-2; sohn[i] = sohn[i].eintragen(wort,ab+1); return this; } /** * Iterator zu Trie erstellen und zurueckgeben. */ public Iterator iterator () { return new TrieIterator(this); } public String toString(int tabs) { String erg = "[ {"; Iterator woerter = wortliste.iterator(); if (woerter.hasNext()) erg += woerter.next(); 4 while (woerter.hasNext()) erg += ","+woerter.next(); erg += "}\n" + prefix(tabs); for (int i = 0; i < 7; i++) erg += (i+2) + ":" + sohn[i].toString(tabs+1)+"\n" + prefix(tabs); erg += 9 + ":" + sohn[7].toString(tabs+1); return erg; } } ////////////////////////////////////////////////////////////////// import java.util.*; public class T9Test { public static void main(String[] args) { Trie myTrie = new Trie(); myTrie.eintragen ("VOM", 0); myTrie.eintragen ("TOM", 0); myTrie.eintragen ("VON", 0); myTrie.eintragen ("TON", 0); myTrie.eintragen ("UNO", 0); myTrie.eintragen ("AB", 0); myTrie.eintragen ("BAR", 0); // myTrie.eintragen ("BEATE", 0); // myTrie.eintragen ("LOTHAR", 0); // myTrie.eintragen ("DOMINIK", 0); System.out.println("myTrie iteriert:\n"+ "================"); Iterator it = myTrie.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } } //Ergebnis : // myTrie iteriert: // ================ // AB // BAR // BEATE // DOMINIK // LOTHAR // VOM // TOM // VON // TON // UNO 5 ////////////////////////////////////////////////////////////////// import java.util.*; /** * Iterator fuer Klasse EmptyTrie. */ public class EmptyTrieIterator implements Iterator { /** * Konstruktor fuer EmptyTrie-Iteratoren. */ EmptyTrieIterator () {} public boolean hasNext() { return false; } public String next() { return "FEHLER: EmptyTrieIterator.next() aufgerufen!"; } public void remove() {} } ////////////////////////////////////////////////////////////////// import java.util.*; /** * Iterator fuer Klasse Trie. */ public class TrieIterator implements Iterator { Trie baum; Iterator akt; int bi; // Index des als naechstes zu betrachtenden Sohn-Iterators. /** * Hilfsmethode: Findet den naechsten Iterator, der noch * Elemente enthaelt - sofern es einen solchen gibt. */ private void finde() { while (bi < 8 && ! akt.hasNext()) { akt = ((T9Trie)baum.getSohn()[bi]).iterator(); bi++; } } /** * Konstruktor fuer Trie-Iteratoren. */ TrieIterator (Trie b) { baum = b; akt = baum.getWortliste().iterator(); 6 bi = 0; finde(); // Evtl. hat akt keine Elemente ... } public boolean hasNext() { return akt.hasNext(); } public String next() { String erg = (String) akt.next(); finde(); return erg; } public void remove() {} } 7 Lösung 10 (Quadtrees) a) EmptyQuadTree enthält keine Attribute, da keine Unterknoten oder Informationen für Objekte dieser Klasse zu speichern sind. QuadTreeElement besitzt ein Koord-Attribut, um die Koordinate abzulegen. Weiterhin werden vier weitere Attribute für die Objekte der Unterbäume benötigt. Dieses können einerseits vier verschiedene Attribute oder andererseits ein Array sein. b) In dieser Graphik sind die EmptyQuadTree-Objekte nicht als schwarze Punkte gekennzeichnet. c) Zur Lösung wurde die Klasse QuadTree etwas erweitert: import java.util.*; public abstract class QuadTree{ public final static QuadTree empty(){ return new EmptyQuadTree(); } 8 public abstract boolean isEmpty(); public abstract QuadTree insert(Koord newK); public abstract boolean contains(Koord k); public abstract Iterator iterator(); public abstract String toString(String ind); } Die Klasse QuadTreeElement (mit Lösung aus d) ): import java.util.*; public class QuadTreeElement extends QuadTree{ public Koord k; public QuadTree[] q; // | // 1|0 // --------// 2|3 // | public QuadTreeElement(Koord k){ this.k = k; q = new QuadTree[4]; q[0] = empty(); q[1] = empty(); q[2] = empty(); q[3] = empty(); } public QuadTree getSubTree(int number){ return q[number]; } public boolean contains(Koord k2){ if(k2 == null) return false; if(k2.equals(k)) return true; return q[inSubTree(k2)].contains(k2); } public boolean isEmpty(){ return false; } public QuadTree insert(Koord newK){ if(k.equals(newK)) return this; int quadrant = inSubTree(newK); q[quadrant] = q[quadrant].insert(newK); return this; } 9 private int inSubTree(Koord p){ if(p.getX()>=k.getX()){ if(p.getY()>=k.getY()) return 0; return 3; }else{ if(p.getY()>=k.getY()) return 1; return 2; } } public Koord getKoord(){ return k; } public Iterator iterator(){ return new QuadTreeIterator(this); } public String toString(String ind){ return ind+"QuadTree:"+this.k.toString()+ "\n"+q[0].toString(ind+" ")+ "\n"+q[1].toString(ind+" ")+ "\n"+q[2].toString(ind+" ")+ "\n"+q[3].toString(ind+" "); } } Die Klasse EmptyQuadTree: import java.util.*; public class EmptyQuadTree extends QuadTree{ public EmptyQuadTree(){ super(); } public boolean isEmpty(){ return true; } public Iterator iterator(){ return new QuadTreeIterator(this); } public QuadTree insert(Koord newK){ return new QuadTreeElement(newK); } public String toString(String ind){ return ind+"Empty"; } public boolean contains(Koord k) { return false; } } 10 d) siehe c) e) import java.util.*; public class QuadTreeIterator implements Iterator { private int curSubTree; private Iterator currentIterator; private QuadTreeElement qt; public QuadTreeIterator(EmptyQuadTree qt) { this.qt = null; this.currentIterator = null; this.curSubTree = 5; } public QuadTreeIterator(QuadTreeElement qt) { this.qt = qt; this.curSubTree = 0; this.currentIterator = qt.getSubTree(0).iterator(); } public boolean hasNext() { return curSubTree != 5; } public void remove() {} public Object next(){ if(!hasNext()) throw new NoSuchElementException(); // Alle SubTrees durchgelaufen => "qt" zurückgeben if(curSubTree == 4) { curSubTree++; return qt; } if(currentIterator.hasNext()) return currentIterator.next(); else{ // aktueller Iterator leer => nächster SubTree curSubTree++; // Solange curSubTree einen vorhandenen SubTree // bezeichnet, den Iterator davon erzeugen if(curSubTree <= 3) currentIterator = qt.getSubTree(curSubTree).iterator(); // rekursiv diese Methode aufrufen return next(); } } } 11