This commit is contained in:
2023-05-24 15:03:40 +02:00
parent eab1c93cfd
commit 77de70cd20
14 changed files with 551 additions and 0 deletions

308
AuD/src/UEB07/AVLBaum.java Normal file
View 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();
}
}

View 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();
}
}

View 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
View 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();
}
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
package UEB07;
public class BaumTest
{
public static void main(String[] args)
{
new BaumGUI().setVisible(true);
}
}