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

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.