Files
2011-10-26 10:11:42 +02:00

230 lines
5.0 KiB
Java

/*
* Eine Knoten-Klasse für die Implementierung von Bäumen.
* Hab's mal ganz edel mit Comparables statt einfach mit
* int-Werten gemacht.
*/
class Node {
/*
* Wir definieren alle unsere Bäume in derselben Package,
* deswegen sind die Variablen durch das protected-Attribut
* vor Zugriff von außen (aus anderen Packages) geschützt.
* Man könnte auch "ordentlich" kapseln und Getter- & Setter-
* Methoden verwenden, was den Code aber extrem aufblähen
* würde.
*/
protected Comparable value; // Wert
protected Node left; // linker Kind-Knoten
protected Node right; // rechter Kind-Knoten
public Node(Comparable value, Node left, Node right) {
this.value = value;
this.left = left;
this.right = right;
}
}
/*
* Dieses Interface dient dazu, Baumimplementierungen vor
* "unqualifizierten" Zugriffen von außen zu schützen. (Damit
* z.B. nicht irgendwelche Knoten direkt in die Datenstruktur
* eingefügt werden, ohne die Sortierung zu beachten, etc.
*/
interface BinaryTree {
public void insert(Comparable value);
public void remove(Comparable value);
}
/*
* Eine Implementierung des BinaryTree-Interface
*/
public class BinTree implements BinaryTree {
Node root;
public BinTree(Node root) {
this.root = root;
}
/*
* Fügt ein Element in den Binärbaum ein.
* (Mehrfaches einfügen ist erlaubt.)
*/
public void insert(Comparable value) {
Node temp = root;
Node parent = null;
while (temp != null) {
parent = temp;
if (value.compareTo(temp.value) < 0) {
temp = temp.left;
}
else {
temp = temp.right;
}
}
if (parent != null) {
if (value.compareTo(parent.value) > 0) {
parent.right = new Node(value, null, null);
}
else {
parent.left = new Node(value, null, null);
}
}
}
/*
* Ersetzt das zu löschende Element mit dem
* größten Element aus dem linken Unterbaum
*/
public void remove(Comparable value) {
Node temp = root;
Node parent = null;
// Knoten suchen
while ((temp != null) && (temp.value.compareTo(value) != 0)) {
parent = temp;
if (value.compareTo(temp.value) < 0) {
temp = temp.left;
}
else {
temp = temp.right;
}
}
// wenn gefunden, Knoten löschen
if (temp != null) {
// wenn linker Unterbaum existiert, mit größtem Element daraus ersetzen
if (temp.left != null) {
Node temp2 = temp.left; // der Knoten, der nach oben versetzt wird
Node parent2 = temp; // der Elternknoten von dem, der nach oben versetzt wird
while (temp2.right != null) {
parent = temp2;
temp2 = temp2.right;
}
if (temp2 != temp.left) temp2.left = temp.left;
temp2.right = temp.right;
parent2.right = temp2.left;
if (parent.left == temp) {
parent.left = temp2;
}
else {
parent.right = temp2;
}
}
else { // sonst einfach mit rechtem Unterbaum ersetzen
if (parent.left == temp) {
parent.left = temp.right;
}
else {
parent.right = temp.right;
}
}
}
}
/*
* Gibt den Baum als AVL-Baum zurück
*/
public static BinTree getAvlTree(BinTree b) {
// TODO
return null;
}
/*
* Wir überschreiben die toString-Methode von
* Object, damit sich der Baum leicht ausgeben lässt
* (s. main-Methode).
*
* ACHTUNG: Die Methode is HÖLLE langsam, weil massen-
* haft Strings konkateniert werden. Schnell implementiert,
* aber extrem unperformant.
*/
public String toString() {
return getTreeAsString(root);
}
private String getTreeAsString(Node n) {
if (n != null) {
//System.out.println(n.value);
return "(" + getTreeAsString(n.left) + ") " + n.value + " (" + getTreeAsString(n.right) + ")";
}
return "*";
}
public static void main(String[] args) {
/*
* Also - Bau'n wir'n Baum:
*
* 10
* .----------'---------.
* 7 12
* .----'----. .----'----.
* 5 9 11 15
* .-' .-'
* 2 8
*
* ...und dann löschen wir die 7:
*
* 10
* .----------'---------.
* 5 12
* .----'----. .----'----.
* 2 9 11 15
* .--'
* 8
*
*/
BinTree tree = new BinTree( new Node(new Integer(10), null, null) );
tree.insert(new Integer(7));
tree.insert(new Integer(12));
tree.insert(new Integer(5));
tree.insert(new Integer(9));
tree.insert(new Integer(11));
tree.insert(new Integer(15));
tree.insert(new Integer(2));
tree.insert(new Integer(8));
System.out.println(tree);
tree.remove(new Integer(7));
System.out.println(tree);
}
}