a
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
package UEB07;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class AVLBaum<T extends Comparable<T>>
|
||||
{
|
||||
private AVLKnoten<T> wurzel;
|
||||
private boolean hoeheGeaendert;
|
||||
|
||||
// Wird nur f�r grafische Oberfl�che ben�tigt, ohne
|
||||
// diese Methode k�nnte die gesamte Implementierung
|
||||
// des Baumes geheim gehalten werden. Alle �ffentlichen
|
||||
// Methoden sind parameterlos oder besitzen als
|
||||
// einzigen Parameter einen Schl�sselwert
|
||||
public AVLKnoten<T> getWurzel()
|
||||
{
|
||||
return wurzel;
|
||||
}
|
||||
|
||||
public boolean istLeer()
|
||||
{
|
||||
return (wurzel == null);
|
||||
}
|
||||
|
||||
|
||||
// Methoden zum Suchen
|
||||
|
||||
public boolean suchen(final T daten)
|
||||
{
|
||||
AVLKnoten<T> current = wurzel;
|
||||
System.out.println("a");
|
||||
while(current.getKnotenLinks()!=null && current.getKnotenRechts() != null){
|
||||
if(current.getDaten().equals(daten)){
|
||||
return true;
|
||||
}
|
||||
System.out.println(current.getDaten().compareTo(daten));
|
||||
switch (current.getDaten().compareTo(daten)) {
|
||||
case -1:
|
||||
System.out.println("-1");
|
||||
current = current.getKnotenRechts();
|
||||
break;
|
||||
case 0:
|
||||
System.out.println("0");
|
||||
return true;
|
||||
case 1:
|
||||
System.out.println("1");
|
||||
current = current.getKnotenLinks();
|
||||
break;
|
||||
}
|
||||
System.out.println("check");
|
||||
if(current.getDaten().equals(daten)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
System.out.println("a");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Methoden zum Einf�gen
|
||||
|
||||
public void einfuegen(final T daten)
|
||||
{
|
||||
// Setzen der Merker-Variable hoeheGeandert auf false
|
||||
// Das wird zwar nach einem Links- oder Rechts-Ausgleich gemacht,
|
||||
// aber diese finden nicht statt, wenn ein bereits existierender
|
||||
// Schl�ssel wiederholt eingef�gt wird!
|
||||
hoeheGeaendert = false;
|
||||
|
||||
// Beim Einf�gen wird der Baum neu zusammengesetzt, um Rotationen
|
||||
// zu erm�glichen. Daher tritt hier kein Sonderfall auf, aber die
|
||||
// Wurzel muss neu zugewiesen werden.
|
||||
wurzel = einfuegenKnoten(daten, wurzel);
|
||||
}
|
||||
|
||||
private AVLKnoten<T> einfuegenKnoten(final T daten, AVLKnoten<T> teilbaum)
|
||||
{
|
||||
if (teilbaum == null)
|
||||
{
|
||||
hoeheGeaendert = true;
|
||||
|
||||
return new AVLKnoten<T>(daten, null, null);
|
||||
}
|
||||
|
||||
// Vergleichs-Ergebnis zwischenspeichern, da compareTo()
|
||||
// aufw�ndig sein kann, und das Ergebnis mehrfach ben�tigt
|
||||
// wird
|
||||
final int cmp = daten.compareTo(teilbaum.getDaten());
|
||||
|
||||
if (cmp < 0)
|
||||
{
|
||||
// Einzuf�gende Daten sind KLEINER als Daten im aktuellen Knoten
|
||||
// und m�ssen daher im LINKEN Teilbaum eingef�gt werden
|
||||
teilbaum.setKnotenLinks(einfuegenKnoten(daten, teilbaum.getKnotenLinks()));
|
||||
if (hoeheGeaendert)
|
||||
teilbaum = linksAusgleich(teilbaum);
|
||||
}
|
||||
else
|
||||
if (cmp > 0)
|
||||
{
|
||||
// Einzuf�gende Daten sind GROESSER als Daten im aktuellen Knoten
|
||||
// und m�ssen daher im RECHTEN Teilbaum eingef�gt werden
|
||||
teilbaum.setKnotenRechts(einfuegenKnoten(daten, teilbaum.getKnotenRechts()));
|
||||
if (hoeheGeaendert)
|
||||
teilbaum = rechtsAusgleich(teilbaum);
|
||||
}
|
||||
|
||||
return teilbaum;
|
||||
}
|
||||
|
||||
private AVLKnoten<T> linksAusgleich(AVLKnoten<T> k)
|
||||
{
|
||||
AVLKnoten<T> x;
|
||||
|
||||
switch (k.getBalance())
|
||||
{
|
||||
case +1:
|
||||
{
|
||||
k.setBalance(0); // Der mit k beginnende Teilbaum ist jetzt balanciert
|
||||
hoeheGeaendert = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0: // Der mit k beginnende Teilbaum ist jetzt linkslastig
|
||||
{
|
||||
k.setBalance(-1);
|
||||
break;
|
||||
}
|
||||
|
||||
case -1: // Ausgleich notwendig
|
||||
{
|
||||
x = k.getKnotenLinks();
|
||||
|
||||
if (x.getBalance() == -1) // Fall 3a
|
||||
{
|
||||
k = rechtsRotation(k, x);
|
||||
}
|
||||
else
|
||||
if (x.getBalance() == +1) // Fall 3b
|
||||
{
|
||||
k = lrDoppelRotation(k, x);
|
||||
k.setBalance(0);
|
||||
}
|
||||
|
||||
k.setBalance(0);
|
||||
hoeheGeaendert = false;
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
private AVLKnoten<T> rechtsAusgleich(AVLKnoten<T> k)
|
||||
{
|
||||
AVLKnoten<T> x;
|
||||
|
||||
switch (k.getBalance())
|
||||
{
|
||||
case -1:
|
||||
{
|
||||
k.setBalance(0); // Der mit k beginnende Teilbaum ist jetzt balanciert
|
||||
hoeheGeaendert = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case 0: // Der mit k beginnende Teilbaum ist jetzt rechtslastig
|
||||
{
|
||||
k.setBalance(+1);
|
||||
break;
|
||||
}
|
||||
|
||||
case +1: // Ausgleich notwendig
|
||||
{
|
||||
x = k.getKnotenRechts();
|
||||
|
||||
if (x.getBalance() == +1) // Fall 3a
|
||||
{
|
||||
k = linksRotation(k, x);
|
||||
}
|
||||
else
|
||||
if (x.getBalance() == -1) // Fall 3b
|
||||
{
|
||||
k = rlDoppelRotation(k, x);
|
||||
}
|
||||
|
||||
k.setBalance(0);
|
||||
hoeheGeaendert = false;
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
private AVLKnoten<T> rechtsRotation(AVLKnoten<T> k, AVLKnoten<T> x)
|
||||
{
|
||||
k.setKnotenLinks(x.getKnotenRechts());
|
||||
x.setKnotenRechts(k);
|
||||
k.setBalance(0);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
private AVLKnoten<T> lrDoppelRotation(AVLKnoten<T> k, AVLKnoten<T> x)
|
||||
{
|
||||
AVLKnoten<T> y = x.getKnotenRechts();
|
||||
x.setKnotenRechts(y.getKnotenLinks());
|
||||
y.setKnotenLinks(x);
|
||||
k.setKnotenLinks(y.getKnotenRechts());
|
||||
y.setKnotenRechts(k);
|
||||
|
||||
switch (y.getBalance())
|
||||
{
|
||||
case -1:
|
||||
{
|
||||
k.setBalance(+1);
|
||||
x.setBalance(0);
|
||||
break;
|
||||
}
|
||||
case +1:
|
||||
{
|
||||
k.setBalance(0);
|
||||
x.setBalance(-1);
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
k.setBalance(0);
|
||||
x.setBalance(0);
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
private AVLKnoten<T> linksRotation(AVLKnoten<T> k, AVLKnoten<T> x)
|
||||
{
|
||||
k.setKnotenRechts(x.getKnotenLinks());
|
||||
x.setKnotenLinks(k);
|
||||
k.setBalance(0);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
private AVLKnoten<T> rlDoppelRotation(AVLKnoten<T> k, AVLKnoten<T> x)
|
||||
{
|
||||
AVLKnoten<T> y = x.getKnotenLinks();
|
||||
x.setKnotenLinks(y.getKnotenRechts());
|
||||
y.setKnotenRechts(x);
|
||||
k.setKnotenRechts(y.getKnotenLinks());
|
||||
y.setKnotenLinks(k);
|
||||
|
||||
switch (y.getBalance())
|
||||
{
|
||||
case +1:
|
||||
{
|
||||
k.setBalance(-1);
|
||||
x.setBalance(0);
|
||||
break;
|
||||
}
|
||||
case -1:
|
||||
{
|
||||
k.setBalance(0);
|
||||
x.setBalance(+1);
|
||||
break;
|
||||
}
|
||||
case 0:
|
||||
{
|
||||
k.setBalance(0);
|
||||
x.setBalance(0);
|
||||
}
|
||||
}
|
||||
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
// Methode zum Traversieren
|
||||
|
||||
// Pre-Order
|
||||
public String traversierePreOrder()
|
||||
{
|
||||
if (wurzel == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
Deque<AVLKnoten> nodeStack = new LinkedList<>();
|
||||
nodeStack.push(wurzel);
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
while (!nodeStack.isEmpty()) {
|
||||
AVLKnoten node = nodeStack.pop();
|
||||
sb.append(node.getDaten()).append(" ");
|
||||
|
||||
if (node.getKnotenRechts() != null) {
|
||||
nodeStack.push(node.getKnotenRechts());
|
||||
}
|
||||
if (node.getKnotenLinks() != null) {
|
||||
nodeStack.push(node.getKnotenLinks());
|
||||
}
|
||||
}
|
||||
|
||||
return sb.toString().trim();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package UEB07;
|
||||
public class AVLKnoten<T>
|
||||
{
|
||||
private T daten;
|
||||
private AVLKnoten<T> teilbaumLinks;
|
||||
private AVLKnoten<T> teilbaumRechts;
|
||||
private int balance; // -1 linkslastig; 0 ausgeglichen; +1 rechtslastig
|
||||
|
||||
public AVLKnoten(T daten, AVLKnoten<T> teilbaumLinks, AVLKnoten<T> teilbaumRechts)
|
||||
{
|
||||
this.daten = daten;
|
||||
this.teilbaumLinks = teilbaumLinks;
|
||||
this.teilbaumRechts = teilbaumRechts;
|
||||
this.balance = 0;
|
||||
}
|
||||
|
||||
public T getDaten()
|
||||
{
|
||||
return daten;
|
||||
}
|
||||
|
||||
public AVLKnoten<T> getKnotenLinks()
|
||||
{
|
||||
return teilbaumLinks;
|
||||
}
|
||||
|
||||
public AVLKnoten<T> getKnotenRechts()
|
||||
{
|
||||
return teilbaumRechts;
|
||||
}
|
||||
|
||||
public int getBalance()
|
||||
{
|
||||
return balance;
|
||||
}
|
||||
|
||||
public void setDaten(T daten)
|
||||
{
|
||||
this.daten = daten;
|
||||
}
|
||||
|
||||
public void setKnotenLinks(AVLKnoten<T> teilbaumLinks)
|
||||
{
|
||||
this.teilbaumLinks = teilbaumLinks;
|
||||
}
|
||||
|
||||
public void setKnotenRechts(AVLKnoten<T> teilbaumRechts)
|
||||
{
|
||||
this.teilbaumRechts = teilbaumRechts;
|
||||
}
|
||||
|
||||
public void setBalance(int balance)
|
||||
{
|
||||
this.balance = balance;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return this.daten.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package UEB07;
|
||||
import java.awt.*;
|
||||
|
||||
public class BaumAnsicht
|
||||
{
|
||||
private AVLBaum<Character> einBaum;
|
||||
|
||||
public BaumAnsicht(AVLBaum<Character> einBaum)
|
||||
{
|
||||
this.einBaum = einBaum;
|
||||
}
|
||||
|
||||
public void ausgeben(int xLinks, int xRechts, int y, Graphics g)
|
||||
{
|
||||
g.setColor(new Color(240, 240, 240));
|
||||
g.fillRect(xLinks, 100, xRechts, 190);
|
||||
|
||||
ausgebenTeilbaum(einBaum.getWurzel(), -1, -1, xLinks, xRechts, y, g);
|
||||
}
|
||||
|
||||
public void ausgebenTeilbaum(AVLKnoten teilbaum, int xParent, int yParent, int xLinks, int xRechts, int y, Graphics g)
|
||||
{
|
||||
if (teilbaum != null)
|
||||
{
|
||||
final int mitte = (xLinks + xRechts) / 2;
|
||||
|
||||
g.setColor(Color.black);
|
||||
g.drawString(teilbaum.toString(), mitte - 2, y);
|
||||
|
||||
if ((xParent != -1) && (yParent != -1))
|
||||
{
|
||||
g.setColor(new Color(192, 192, 192));
|
||||
g.drawLine(xParent, yParent, mitte, y-12);
|
||||
}
|
||||
|
||||
ausgebenTeilbaum(teilbaum.getKnotenLinks(), mitte, y + 4, xLinks + 4, mitte - 4, y + 30, g);
|
||||
ausgebenTeilbaum(teilbaum.getKnotenRechts(), mitte, y + 4, mitte + 4, xRechts + 4, y + 30, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package UEB07;
|
||||
import java.awt.*;
|
||||
import java.applet.*;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
|
||||
public class BaumGUI extends Frame
|
||||
{
|
||||
private AVLBaum<Character> einBaum;
|
||||
private BaumAnsicht eineBaumAnsicht;
|
||||
|
||||
private java.awt.Label zeichenFuehrungstext = new java.awt.Label();
|
||||
private java.awt.TextField zeichenTextfeld = new java.awt.TextField();
|
||||
private java.awt.Button einfuegenDruckknopf = new java.awt.Button();
|
||||
private java.awt.Button suchenDruckknopf = new java.awt.Button();
|
||||
private java.awt.Checkbox enthaltenKontrollkaestchen = new java.awt.Checkbox();
|
||||
private java.awt.TextArea ausgabeTextfeld = new java.awt.TextArea("",0,0,TextArea.SCROLLBARS_NONE);
|
||||
private java.awt.Button traversierenDruckknopf = new java.awt.Button();
|
||||
|
||||
public BaumGUI()
|
||||
{
|
||||
setLayout(null);
|
||||
setSize(530,485);
|
||||
zeichenFuehrungstext.setText("Zeichen:");
|
||||
zeichenFuehrungstext.setAlignment(java.awt.Label.RIGHT);
|
||||
add(zeichenFuehrungstext);
|
||||
zeichenFuehrungstext.setBounds(12,32,48,24);
|
||||
add(zeichenTextfeld);
|
||||
zeichenTextfeld.setBounds(72,32,48,24);
|
||||
einfuegenDruckknopf.setLabel("Einf�gen");
|
||||
add(einfuegenDruckknopf);
|
||||
einfuegenDruckknopf.setBackground(java.awt.Color.lightGray);
|
||||
einfuegenDruckknopf.setBounds(228,32,84,24);
|
||||
suchenDruckknopf.setLabel("Suchen");
|
||||
add(suchenDruckknopf);
|
||||
suchenDruckknopf.setBackground(java.awt.Color.lightGray);
|
||||
suchenDruckknopf.setBounds(132,32,84,24);
|
||||
enthaltenKontrollkaestchen.setLabel("Im Baum enthalten");
|
||||
enthaltenKontrollkaestchen.setEnabled(false);
|
||||
add(enthaltenKontrollkaestchen);
|
||||
enthaltenKontrollkaestchen.setBounds(132,68,132,24);
|
||||
add(ausgabeTextfeld);
|
||||
ausgabeTextfeld.setBounds(14,330,500,144);
|
||||
traversierenDruckknopf.setLabel("Traversieren");
|
||||
add(traversierenDruckknopf);
|
||||
traversierenDruckknopf.setBackground(java.awt.Color.lightGray);
|
||||
traversierenDruckknopf.setBounds(14,300,127,26);
|
||||
|
||||
AktionsAbhoerer einAktionsAbhoerer = new AktionsAbhoerer();
|
||||
einfuegenDruckknopf.addActionListener(einAktionsAbhoerer);
|
||||
suchenDruckknopf.addActionListener(einAktionsAbhoerer);
|
||||
TastaturAbhoerer einTastaturAbhoerer = new TastaturAbhoerer();
|
||||
zeichenTextfeld.addKeyListener(einTastaturAbhoerer);
|
||||
traversierenDruckknopf.addActionListener(einAktionsAbhoerer);
|
||||
|
||||
addWindowListener(
|
||||
new WindowAdapter()
|
||||
{
|
||||
public void windowClosing(WindowEvent event)
|
||||
{
|
||||
setVisible(false);
|
||||
dispose();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
einBaum = new AVLBaum<Character>();
|
||||
eineBaumAnsicht = new BaumAnsicht(einBaum);
|
||||
}
|
||||
|
||||
public void paint(Graphics g)
|
||||
{
|
||||
eineBaumAnsicht.ausgeben(15, 500, 120, g);
|
||||
}
|
||||
|
||||
// Innere Klassen
|
||||
class AktionsAbhoerer implements java.awt.event.ActionListener
|
||||
{
|
||||
public void actionPerformed(java.awt.event.ActionEvent event)
|
||||
{
|
||||
Object object = event.getSource();
|
||||
if ((object == einfuegenDruckknopf) || (object == suchenDruckknopf))
|
||||
{
|
||||
String text = zeichenTextfeld.getText();
|
||||
if ((text != null) && (text.length() > 0))
|
||||
{
|
||||
char zeichen = text.charAt(0);
|
||||
|
||||
if (object == einfuegenDruckknopf)
|
||||
{
|
||||
einBaum.einfuegen(zeichen);
|
||||
zeichenTextfeld.setText("");
|
||||
repaint();
|
||||
}
|
||||
else
|
||||
if (object == suchenDruckknopf)
|
||||
{
|
||||
enthaltenKontrollkaestchen.setState(einBaum.suchen(zeichen));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (object == traversierenDruckknopf)
|
||||
{
|
||||
ausgabeTextfeld.setText("Pre-Order:\n" + einBaum.traversierePreOrder());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TastaturAbhoerer extends java.awt.event.KeyAdapter
|
||||
{
|
||||
public void keyReleased(java.awt.event.KeyEvent event)
|
||||
{
|
||||
if (event.getSource() == zeichenTextfeld)
|
||||
{
|
||||
String text = zeichenTextfeld.getText();
|
||||
if ((text != null) && (text.length() > 0))
|
||||
{
|
||||
char zeichen = text.charAt(0);
|
||||
|
||||
if(event.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER)
|
||||
{
|
||||
einBaum.einfuegen(zeichen);
|
||||
zeichenTextfeld.setText("");
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package UEB07;
|
||||
public class BaumTest
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new BaumGUI().setVisible(true);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user