Aufgabenstellung: Ein vom Benutzer angegebener arithmetischer

Werbung
Algorithmen und Datenstrukturen
Übung 1b: Praktische Nutzung von Bäumen
1. Sets mit binären Suchbäumen
Interface Set
interface Set
{
void add(Comparable o);
boolean contains(Comparable o);
Set unite(Set s);
}
Für die Implementierung dieses Interface ist Voraussetzung:
- effizienten Test auf Enthaltensein
- Implementierung: binärer Suchbaum (Klassen TreeNode, BinaryTree)
Klasse TreeNode
public class TreeNode
{
protected Object element;
protected TreeNode left, right;
int x = 0; int y = 0;
public TreeNode(Object o)
{
left = right = null;
element = o;
}
public TreeNode getLeft() { return left; }
public TreeNode getRight() { return right; }
public Object getElement() { return element; }
public void setLeft(TreeNode n) { left = n; }
public void setRight(TreeNode n) { right = n; }
public String toString() { return element.toString(); }
public void accept(NodeVisitor v, int depth)
{
if (left != null)
left.accept(v,depth+1);
v.visitNode(this,depth);
if (right != null)
right.accept(v,depth+1);
}
public void setX(int wert)
{ x = wert; }
public void setY(int wert)
{ y = wert; }
public int getX()
{
return x;
}
public int getY()
{
return y;
}
}
Klasse BinaryTree
1
Algorithmen und Datenstrukturen
public class BinaryTree
{
protected TreeNode root;
protected int size;
public BinaryTree()
{
root = null; size = 0;
}
public int size() { return this.size; }
public boolean isEmpty() { return this.size == 0; }
public TreeNode root()
{ return this.root; }
public boolean contains(Comparable o)
{
TreeNode node = findNode(root,o);
return (o.compareTo(node.getElement()) == 0);
}
protected TreeNode findNode(TreeNode n, Comparable o)
{
int cmp = o.compareTo(n.getElement());
if (cmp < 0 && n.getLeft() != null)
return findNode(n.getLeft(),o);
else if (cmp > 0 && n.getRight() != null)
return findNode(n.getRight(),o);
else return n;
}
public void insert(Comparable o)
{
if (isEmpty()) root = new TreeNode(o);
else {
TreeNode node = findNode(root,o);
int cmp = o.compareTo(node.getElement());
if (cmp == 0) return;
else if (cmp < 0)
node.setLeft(new TreeNode(o));
else node.setRight(new TreeNode(o));
}
size++;
}
}
Klasse TreeSet
public class TreeSet implements Set
{
protected BinaryTree tree;
public TreeSet()
{
tree = new BinaryTree();
}
public int size() { return tree.size(); }
public void add(Comparable o) { tree.insert(o); }
public boolean contains(Comparable o)
{
return tree.contains(o);
}
public TreeSetIterator iterator()
{
return new TreeSetIterator(tree);
}
public TreeSet unite(TreeSet set)
{
2
Algorithmen und Datenstrukturen
// Vereinigung
TreeSet newSet = new TreeSet();
java.util.Iterator i = this.iterator();
while (i.hasNext())
newSet.add((Comparable) i.next());
i = set.iterator();
while (i.hasNext())
newSet.add((Comparable) i.next());
return newSet;
}
}
Implementierung Baum-Iterator
import java.util.*;
public class TreeSetIterator implements java.util.Iterator
{
private BinaryTree tree;
private Stack stack;
public TreeSetIterator(BinaryTree tree)
{
this.tree = tree;
this.stack = new Stack();
TreeNode node = tree.root();
while (node != null)
{
stack.push(node);
node = node.getLeft();
}
}
public boolean hasNext()
{
return !stack.empty();
}
public Object next()
{
Object o;
TreeNode node = (TreeNode) stack.peek();
o = node.getElement();
stack.pop();
if (node.getRight() != null)
{
node = node.getRight();
while (node != null)
{
stack.push(node);
node = node.getLeft();
}
}
return o;
}
public void remove()
{ System.out.println("Nicht implementiert"); }
}
3
Algorithmen und Datenstrukturen
2. Zeichnen von Bäumen
Regeln zum Zeichnen von Bäumen
- x-Position: Anzahl der Knoten, die zuvor "inorder" besichtigt werden
- y-Position: Tiefe des Knotens im Baum.
Mit dieser Funktionalität ist der abstrake Datentyp eines Binärbaumknotens (Klasse
TreeNode) auszustatten:
- Bestimmen der Position des Knotens
- Zeichnen des Knotens
Alternativen sind:
- Modifizieren der Klasse
- Spezialisierung
- Visitor
Konzept eines Visitor
- Ganz allgemein kann man von einer Collection verlangen, dass einem Besucher (Visitor) alle
Insassen (Elemente) genau einmal vorgestellt werden.
- Ein beliebiges Objekt ist ein Visitor, wenn ihm Objekte vorgeführt werden können
- Interface Visitor: Methode mit der die Kollektion (Collection) dem Visitor ihre Insassen vorstellt.
- Beim Suchbaum hat man die Möglichkeit, Einträge sortiert auszugeben.
- Ein Suchbaum sollte Visitable sein, um die Sortierung auszunutzen.
- Implementiert man einen Visitor, der die Insassen in einem Stringbuffer abbildet, kann man den
Baum sehr elegant darstellen lassen.
Die Schnittstelle Visitor
public interface NodeVisitor
{
public void visitNode(TreeNode n, int depth);
}
Anwendung der Schnittstelle
- Erzeugen eines Visitors:
- Start beim Wurzelknoten:
- Aufruf der Methode visitNode() für jeden besuchten Knoten.
Visitor-Unterstützung in TreeNode
public void accept(NodeVisitor v, int depth)
{
if (left != null)
left.accept(v,depth+1);
v.visitNode(this,depth);
4
Algorithmen und Datenstrukturen
if (right != null)
right.accept(v,depth+1);
}
Bestimmen der Position: ArrangeVisitor
public class ArrangeVisitor implements NodeVisitor
{
private int rank = 0;
public ArrangeVisitor(){ }
public void visitNode(TreeNode node,int depth)
{
node.setX(rank++ * 30);
node.setY(depth * 30);
}
}
Zeichnen der Knoten: DrawVisitor
public class DrawVisitor implements NodeVisitor
{
private java.awt.Graphics g;
public DrawVisitor(java.awt.Graphics g)
{ this.g = g; }
public void visitNode(TreeNode node, int depth)
{
g.drawString(node.getElement().toString(),
node.getX() + 15, node.getY());
g.fillOval(node.getX(),node.getY(),20,20);
if (node.getLeft() != null)
{
g.drawLine(node.getX() + 10, node.getY() + 10,
node.getLeft().getX() + 10,
node.getLeft().getY() + 10);
}
if (node.getRight() != null)
{
g.drawLine(node.getX() + 10, node.getY() + 10,
node.getRight().getX() + 10,
node.getRight().getY() + 10);
}
}
}
Darstellung eines binären Suchbaums
5
Algorithmen und Datenstrukturen
3. Darstellung eines binären Suchbaums mit den Swing-Komponenten für binäre
Bäume
Zur grafischen Darstellung von Bäumen werden mit Swing neue Interfaces und
Klassen eingeführt, die im Paket javax.swing.tree zusammengefasst sind.
BinaryTreeModel
Die
Klasse
BinaryTreeModel
javax.swing.tree.TreeModel.
implementiert
import javax.swing.event.*;
import javax.swing.tree.*;
public class BinaryTreeModel
implements javax.swing.tree.TreeModel
{
BinaryTree tree;
public BinaryTreeModel(BinaryTree tree)
{
this.tree = tree;
}
public Object getRoot()
{
return tree.root();
}
public Object getChild(Object parent,int index)
{
if (index == 0)
{
if (((TreeNode)parent).getLeft() == null )
return ((TreeNode)parent).getRight();
return ((TreeNode)parent).getLeft();
}
else if (index == 1)
return ((TreeNode)parent).getRight();
else
6
die
Schnittstelle
Algorithmen und Datenstrukturen
return null;
}
public boolean isLeaf(Object node)
{
if ( ((TreeNode)node).getLeft() == null &&
((TreeNode)node).getRight() == null)
return true;
else return false;
}
public int getChildCount(Object parent)
{
int i = 0;
if (((TreeNode)parent).getLeft()!= null)
i++;
if (((TreeNode)parent).getRight() != null) i++;
return i;
}
public int getIndexOfChild(Object parent,Object child)
{
// liefert den Index von child bzgl. parent
if (parent == null || child == null)
{
return -1;
}
if ( ((TreeNode)parent).getLeft().equals(child))
{
return 0;
}
if ( ((TreeNode)parent).getRight().equals(child))
{
return 1;
}
return -1;
}
public void valueForPathChanged(TreePath path, Object newValue)
{
}
public void addTreeModelListener(TreeModelListener l)
{
}
public void removeTreeModelListener(TreeModelListener l)
{
}
}
BinaryTreeTest
import
import
import
import
java.awt.*;
javax.swing.*;
javax.swing.tree.*;
javax.swing.event.*;
public class BinaryTreeTest extends JFrame
{
public BinaryTreeTest()
{
super("Erzeugen eines binaeren Baums");
BinaryTree tree = new BinaryTree();
for (int i=0; i< 20; i++)
{
String s = "Zufallszahl " + (int)(Math.random() * 100);
tree.insert(s);
}
7
Algorithmen und Datenstrukturen
BorderLayout borderLayout = new BorderLayout();
JTree jTree = new JTree();
jTree.setModel(new BinaryTreeModel(tree));
JScrollPane scrollPane = new JScrollPane(jTree);
Container contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(borderLayout);
contentPane.add(scrollPane,BorderLayout.CENTER);
// scrollPane.getViewport().add(jTree,null);
setSize(300,300);
setVisible(true);
}
public static void main(String args[])
{
new BinaryTreeTest();
}
}
Darstellung
8
Herunterladen