a
This commit is contained in:
308
AuD/src/UEB07/AVLBaum.java
Normal file
308
AuD/src/UEB07/AVLBaum.java
Normal file
@@ -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<66>che ben<65>tigt, ohne
|
||||
// diese Methode k<>nnte die gesamte Implementierung
|
||||
// des Baumes geheim gehalten werden. Alle <20>ffentlichen
|
||||
// Methoden sind parameterlos oder besitzen als
|
||||
// einzigen Parameter einen Schl<68>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<6E>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<68>ssel wiederholt eingef<65>gt wird!
|
||||
hoeheGeaendert = false;
|
||||
|
||||
// Beim Einf<6E>gen wird der Baum neu zusammengesetzt, um Rotationen
|
||||
// zu erm<72>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<66>ndig sein kann, und das Ergebnis mehrfach ben<65>tigt
|
||||
// wird
|
||||
final int cmp = daten.compareTo(teilbaum.getDaten());
|
||||
|
||||
if (cmp < 0)
|
||||
{
|
||||
// Einzuf<75>gende Daten sind KLEINER als Daten im aktuellen Knoten
|
||||
// und m<>ssen daher im LINKEN Teilbaum eingef<65>gt werden
|
||||
teilbaum.setKnotenLinks(einfuegenKnoten(daten, teilbaum.getKnotenLinks()));
|
||||
if (hoeheGeaendert)
|
||||
teilbaum = linksAusgleich(teilbaum);
|
||||
}
|
||||
else
|
||||
if (cmp > 0)
|
||||
{
|
||||
// Einzuf<75>gende Daten sind GROESSER als Daten im aktuellen Knoten
|
||||
// und m<>ssen daher im RECHTEN Teilbaum eingef<65>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();
|
||||
}
|
||||
|
||||
}
|
||||
61
AuD/src/UEB07/AVLKnoten.java
Normal file
61
AuD/src/UEB07/AVLKnoten.java
Normal file
@@ -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();
|
||||
}
|
||||
}
|
||||
40
AuD/src/UEB07/BaumAnsicht.java
Normal file
40
AuD/src/UEB07/BaumAnsicht.java
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
134
AuD/src/UEB07/BaumGUI.java
Normal file
134
AuD/src/UEB07/BaumGUI.java
Normal file
@@ -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<EFBFBD>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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
8
AuD/src/UEB07/BaumTest.java
Normal file
8
AuD/src/UEB07/BaumTest.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package UEB07;
|
||||
public class BaumTest
|
||||
{
|
||||
public static void main(String[] args)
|
||||
{
|
||||
new BaumGUI().setVisible(true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user