From fd1893cfd8a47fdcc6f27b3500237a4eff4866d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Mei=C3=9Fner?= <daniel@3st.mine.nu>
Date: Sun, 24 Jun 2012 22:03:59 +0200
Subject: [PATCH] Added lesson 9 exercise 1.

---
 Aufgabenblatt_9-Aufgabe_1/src/AVLTree.java    | 254 ++++++++++++++++++
 .../src/Aufgabenblatt_9Aufgabe_1.java         |  17 ++
 2 files changed, 271 insertions(+)
 create mode 100644 Aufgabenblatt_9-Aufgabe_1/src/AVLTree.java
 create mode 100644 Aufgabenblatt_9-Aufgabe_1/src/Aufgabenblatt_9Aufgabe_1.java

diff --git a/Aufgabenblatt_9-Aufgabe_1/src/AVLTree.java b/Aufgabenblatt_9-Aufgabe_1/src/AVLTree.java
new file mode 100644
index 0000000..32ad260
--- /dev/null
+++ b/Aufgabenblatt_9-Aufgabe_1/src/AVLTree.java
@@ -0,0 +1,254 @@
+public class AVLTree<T extends Comparable<T>> {
+
+    private class Node {		// ein Knoten im Baum
+	T    value;			// Wert am Knoten
+        Node left;			// Wurzel linker Unterbaum
+	Node right;			// Wurzel rechter Unterbaum
+	int  balance;			// hoehe(linker Unterbaum) - hoehe(rechter Unterbaum)
+
+	Node(T val) {
+	    value = val;
+	    left = null;
+	    right = null;
+	    balance = 0;
+	}
+    }
+
+    private Node root;			// Wurzel des gesamten AVL-Baums
+    private int size;			// Anzahl Knoten im AVL-Baum
+
+    public AVLTree() {
+        root = null;
+	size = 0;
+    }
+
+    public int size() {
+        return size;
+    }
+
+    public boolean contains(T elem) {
+        Node node = root;
+        int  diff;
+
+	while (node != null) {
+	    diff = node.value.compareTo(elem);
+	    if (diff == 0) {
+	        return true;
+	    }
+	    else if (diff>0) {
+	        node = node.left;
+	    }
+	    else {
+	        node = node.right;
+	    }
+	}
+
+	return false;
+    }
+
+    public void insert(T elem) {
+      insert(root,null,elem);
+    }
+
+    /*
+     * Rekursives Einfuegen in einen Unterbaum.
+     *
+     * node: Der Wurzelknoten des Baumes bzw. Unterbaums, in den eingefuegt wird.
+     * father: Vaterknoten von node, node ist linker oder rechter Sohn von father
+     * elem: Der einzufuegende Wert
+     *
+     * return: true, falls der Unterbaum durch das Einfuegen hoeher geworden ist,
+     *    sonst false
+     */
+    private boolean insert(Node node, Node father, T elem) {
+      int     diff;
+      boolean grown;
+      int     balanceDelta;
+
+      if (node==null) {			// am leeren Unterbaum angekommen
+        node=new Node(elem);		// dann wird hier ein neuer Knoten erzeugt
+        if (father==null) {			// nur moeglich, wenn der root==null also insgesamt leerer Baum
+	        root = node;			// dann besteht der Baum jetzt aus genau einem Knoten
+        }					// ansonsten muessen wir untersuchen, ob der neue Knoten
+        else if (father.value.compareTo(elem) > 0) {	// linker oder rechter Sohn seines Vaters wird.
+	        father.left = node;		// Wert im Vater ist groesser, dann wird neuer Knoten
+        }					// linker Sohn
+        else {				// Wert im Vater ist kleiner, dann wird neuer Knoten
+	        father.right = node;		// rechter Sohn
+        }
+        
+        size++;				// Baum hat insgesamt einen Knoten mehr
+        return true;			// Unterbaum mit node als Wurzel ist gewachsen
+       }
+
+	// Wenn wir hier angekommen sind, gilt node != null.
+	// Wir muessen also in einen der beiden Unterbaeume von node einfuegen
+
+      diff = node.value.compareTo(elem);	
+      if (diff == 0) {			// Wert elem schon im Baum vorhanden
+  	    return false;			// kein Einfuegen!
+      }
+      else if (diff > 0) {			// node.value > elem ==> in linken Unterbaum einfuegen
+        grown = insert(node.left,node,elem);
+        balanceDelta = 1;
+      }
+      else {					// node.value < elem ==> in rechten Unterbaum einfuegen
+        grown = insert(node.right,node,elem);
+        balanceDelta = -1;
+      } 
+
+      if (grown) {				// wenn der unterbaum von node, in den wir eingefuegt haben,
+        node.balance += balanceDelta;	// gewachsen ist, dann aendert sich der balance-Wert
+      }					// am Knoten node
+
+      if (!grown || node.balance==0) {	// Keine Hoehenaenderung oder Fall 2 (Folie 253)
+        return false;			// Baum mit Wurzel node ist insgesamt nicht gewachsen
+      }
+
+	// Wenn wir hier angekommen sind, ist der Baum mit node als Wurzel gewachsen.
+	// Es liegt entweder Fall 1 oder Fall 3 vor.
+
+      if (node.balance==1 || node.balance==-1) {	// AVL Kriterium noch erfuellt
+	    return true;				// Fall 1 (Folie 250)
+	}						// Der Baum ist auf jeden Fall gewachsen
+
+	// Wenn wir hier angekommen sind, ist der Baum mit Wurzel node gewachsen und das
+	// AVL-Kriterium ist verletzt.
+        if (node.balance==2) {
+	    if (node.left.balance==1) {
+	        rotateLeftLeft(node);		// Fall 3a (Folie 258)
+	    }
+	    else {
+          rotateLeftRight(node); // LR-Rotation			// Fall 3b (Folie 261)
+	    }
+	}
+	else {
+	    if (node.right.balance==-1) {
+	        rotateLeftRightSymmetric(node);			// Fall symmetrisch zu 3a
+	    }
+	    else {
+	        rotateLeftRightSymmetric(node); // RL-Rotation			// Fall symmterisch zu 3b
+	    }
+	}
+
+        // Ausgleichsrotationen fuehren beim Einfuegen stets dazu, dass der Unterbaum mit
+	// node als Wurzel nicht gewachsen ist.
+
+	return false;
+    }
+
+    private void rotateLeftLeft(Node w) {	// vgl. Folie 258
+      Node v  = w.left;
+      Node a1 = v.left;
+      Node a2 = v.right;
+      Node b  = w.right;
+      T    tmpval;
+      Node tmpnode;
+
+      tmpval = w.value;			// Werte in den Knoten tauschen
+      w.value = v.value;
+      v.value = tmpval;
+
+      tmpnode = w;				// Verweise auf Knoten tauschen
+      w = v;              // damit anschliessend wieder gilt:
+      v = tmpnode;				// in Knoten v liegt v.value und in w liegt w.value
+
+      v.left = a1;				// Verweise umhaengen
+      v.right = w;
+      w.left = a2;
+      w.right = b;
+
+      v.balance = 0;      // Unterbaeume ab v und w sind jetzt auf jeden Fall
+      w.balance = 0;			// vollstaendig ausgeglichen
+    }
+    
+    private void rotateLeftRight(Node w) {
+      Node v  = w.left;
+      Node u  = v.right;
+      Node a1 = v.left;
+      Node a2 = u.left;
+      Node a3 = u.right;
+      Node b  = w.right;
+      T    tmpval;
+      Node tmpnode;
+      
+      tmpval = w.value;			// Werte in den Knoten tauschen
+      w.value = u.value;
+      u.value = tmpval;
+      
+      tmpnode = w;				// Verweise auf Knoten tauschen
+      w = u;              // damit anschliessend wieder gilt:
+      u = tmpnode;				// in Knoten v liegt v.value und in w liegt w.value
+      
+      u.left = v;
+      u.right = w;
+      
+      v.left = a1;
+      v.right = a2;
+      
+      w.left = a3;
+      w.right = b;
+      
+      u.balance = 0;
+      v.balance = 0;
+      w.balance = 0;
+    }
+    
+    private void rotateLeftLeftSymmetric(Node w) {	// vgl. Folie 258
+      Node v  = w.right;
+      Node a1 = v.right;
+      Node a2 = v.left;
+      Node b  = w.left;
+      T    tmpval;
+      Node tmpnode;
+
+      tmpval = w.value;			// Werte in den Knoten tauschen
+      w.value = v.value;
+      v.value = tmpval;
+
+      tmpnode = w;				// Verweise auf Knoten tauschen
+      w = v;              // damit anschliessend wieder gilt:
+      v = tmpnode;				// in Knoten v liegt v.value und in w liegt w.value
+
+      v.right = a1;				// Verweise umhaengen
+      v.left = w;
+      w.right  =  a2;
+      w.left = b;
+
+      v.balance = 0;      // Unterbaeume ab v und w sind jetzt auf jeden Fall
+      w.balance = 0;			// vollstaendig ausgeglichen
+    }
+    
+    
+    private void rotateLeftRightSymmetric(Node w) {
+      Node v  = w.right;
+      Node u  = v.left;
+      Node a1 = v.right;
+      Node a2 = u.right;
+      Node a3 = u.left;
+      Node b  = w.left;
+      T    tmpval;
+      Node tmpnode;
+      
+      tmpval = w.value;			// Werte in den Knoten tauschen
+      w.value = u.value;
+      u.value = tmpval;
+      
+      tmpnode = w;				// Verweise auf Knoten tauschen
+      w = u;              // damit anschliessend wieder gilt:
+      u = tmpnode;				// in Knoten v liegt v.value und in w liegt w.value
+      
+      u.left = v;
+      u.right = w;
+      
+      v.right = a1;
+      v.left = a2;
+      
+      w.right = a3;
+      w.left = b;
+      
+      u.balance = 0;
+      v.balance = 0;
+      w.balance = 0;
+    }
+}
diff --git a/Aufgabenblatt_9-Aufgabe_1/src/Aufgabenblatt_9Aufgabe_1.java b/Aufgabenblatt_9-Aufgabe_1/src/Aufgabenblatt_9Aufgabe_1.java
new file mode 100644
index 0000000..8c36501
--- /dev/null
+++ b/Aufgabenblatt_9-Aufgabe_1/src/Aufgabenblatt_9Aufgabe_1.java
@@ -0,0 +1,17 @@
+public class Aufgabenblatt_9Aufgabe_1 {
+
+  public static void main(String[] args) {
+  
+    AVLTree<Integer> avltree = new AVLTree();
+  
+    avltree.insert(50);
+    avltree.insert(42);
+    avltree.insert(23);
+    avltree.insert(2342);
+    avltree.insert(55);
+    avltree.insert(13);
+    avltree.insert(37);
+
+    System.out.println("Anzahl der Elemente: " + avltree.size());
+  }
+}
-- 
GitLab