Übung 9: Bayer-Bäume - oth

Werbung
Algorithmen und Datenstrukturen
Übung 9: Bayer-Bäume
Bayer-Baumknoten
Die Klasse CBNode zeigt die Implementierung eines Bayer -Baumknotens 1. Der Konstruktor dieser
Klasse leistet die Arbeit und bekommt dazu einen Übergabeparameter (M) geliefert, der die Ordnung
des (M-ären) Bayer-Baums beschreibt.
import java.util.*;
/*
* The CBNode class represents on single Node of the Bayer Tree.
*/
public class CBNode
{
// Instanzvariable
protected Vector key, nodeptr, initkey, initvec;
int count;
// Konstruktor
/*
* constructs a single Bayer Tree node with M references to subnodes.
*/
CBNode(int M)
{
// System.out.println("CBNode(): constructor invoked!");
nodeptr = new Vector();
initvec = new Vector();
initvec = null;
key = new Vector();
initkey = new Vector();
initkey = null;
for(int i = 0; i <= M; i++)
{
nodeptr.addElement((Object)initvec);
// System.out.println(i +
"ter Nodepointer erzeugt. Wert: " + nodeptr.elementAt(i));
}
for(int j = 0; j <= M - 1; j++)
{
key.addElement((Object)initkey);
// System.out.println(j + "ter Key erzeugt. Wert: " + key.elementAt(j));
}
count = 0;
// System.out.println("count Wert: " + count);
}
}
Bayer-Baum
Die Klasse CBayerTree umfaßt den Algorithmus 2 zum Einfügen und Löschen von Bayer-Baum knoten
1 Vgl. pr44200, CBNode.java
2 Vgl. pr44200, CBayerTree.java
1
Algorithmen und Datenstrukturen
class CBayerTree
{
// protected Instanzvariablen
/*
* Die Variable MAERER definiert die Ordnung des Bayer-Baums,
* d.h. der Nachfolgerknoten bzw. Teilbäume eines Knoten
* (max. MAERER). Jeder Knoten besteht aus MAERER Referenzen
* auf Subknoten und MAERER - 1 Schlüsseln.
*/
protected int MAERER = 5;
/*
* contains the reference to the CVisualizeTree class. It will be set in
* the constructor.
*/
protected CVisualizeTree mpCVisualizeTree;
/*
* contains the reference to the CExtendedCanvas class. It will be set in
* the constructor.
*/
protected CExtendedCanvas mpCExtendedCanvas;
/*
* Referenz zum Wurzelknoten während der Lebensdauer des Baums.
*/
protected CBNode root;
/*
* speichert den neuen Schluessel, der in den baum eingefügt werden soll.
*/
protected Integer newValue;
/*
* Indikator fuer den Wurzelknoten.
*/
private int rootflag = 0;
// Public Operationen
// Der Konstruktor umfasst zwei Paramerte zur Visualisierung
/*
public CBayerTree(CExtendedCanvas pCExtendedCanvas,
CVisualizeTree pCVisualizeTree);
Einfuegen
public int Insert(Integer value);
;
Rueckgabe: -1, falls Fehlversuch; anderenfalls 0
Parameter: einzufuegender Schluessel
Loeschen
public int Delete(Integer delValue);
;
Rueckgabe: -1, falls Fehlversuch; anderenfalls 0
Parameter: einzufuegender Schluessel
public boolean searchkey(int key);
Rueckgabe: true, falls der Schlüssel gefunden wurde; anderenfalls
false
Geschuetzte Methoden
protected CBNode insrekurs(CBNode tempnode, Integer insValue);
Private Methoden
private int delrekurs(CBNode delNode, Integer value);
.....
*/
}
2
Algorithmen und Datenstrukturen
Operationen für Bayer-Bäume
Suchen eines Schlüssels
Gegeben ist der folgende Ausschnitt eines B-Baums mit N Schlüsseln:
+-------------------------------+
|
|
| Z 0S 1Z 1S 2 .......... Z N-1S NZ N |
|
|
+-------------------------------+
Beim Suchen eines Schlüssels X können folgende Situationen auftreten:
1) S[I] < X < S[I + 1] für 1 <= I <= N
Die Suche wird fortgesetzt in dem Knoten, auf den Z[I]^ zeigt.
2) S[N] < X
Die Suche wird im Knoten fortgesetzt, auf den Z[N]^ zeigt.
3) X < S[1]
Die Suche wird im Knoten fortgesetzt, auf den Z[0]^ zeigt.
Hat einer der angegebenen Referenzen den Wert „null“, dann existiert in dem vorliegenden Baum
kein Teilbaum, der diesen Schlüssel enthält (d.h. die Suche ist beendet).
/*
*Rueckgabe ist true, falls der Schlüssel gefunden wurde;
* anderenfalls false.
*/
public boolean searchkey(int key)
{
boolean found = false;
int i = 0, n;
CBNode node = root;
while(node != null)
{
i = 0;
n = node.count;
// search key in actual node
while(i < n && key > ((Integer)node.key.elementAt(i)).intValue())
{
i++;
}
// end while
if(i < n && key == ((Integer)node.key.elementAt(i)).intValue())
{
found = true;
}
if(node.nodeptr.elementAt(i) != null)
{
mpCVisualizeTree.MoveLevelDown(i);
}
node = (CBNode) node.nodeptr.elementAt(i);
}
// end while (node != null)
return found;
}
// end searchkey Methode
Einfügen
Bsp.: Der Einfügevorgang in einem Bayer-Baum der Klasse 2
3
Algorithmen und Datenstrukturen
1) Aufnahme der Schlüssel 1, 2, 3, 4 in den Wurzelknoten
1
2
3
4
2) Zusätzlich wird der Schlüssel mit dem Wert 5 eingefügt
1
2
3
4
5
Normalerweise würde jetzt rechts von "4" ein neuer Knotem erzeugt. Das würde aber zu einem
Knotenüberlauf führen. Nach dieser Erweiterung enthält der Knoten eine unge rade Zahl von
Elementen (2 ⋅ M + 1 ). Dieser große Knoten kann in 2 Söhne zerlegt werden, nur das mittlere
Element verbleibt im Vaterknoten. Die neuen Knoten genügen wieder den B-Baum -Eigenschaften und
könnem weitere Daten aufnehmen.
3
1
2
4
5
Beschreibung des Algorithmus für das Einfügen
Ein neues Element wird grundsätzlich in einen Blattknoten eingefügt. Ist der Knoten mit
Schlüsseln voll, so läuft bei der Aufnahme eines weiteren Schlüssels der Knoten über.
2⋅M
+---------------------------------------------+
|
|
| ...........
S X-1Z X-1S XZ X
.....
|
|
|
+---------------------------------------------+
+----------------------------------------------+
|
|
| Z0 S1 Z1 .... ZM-1 SM ZM SM+1 ....... Z 2M S2M+1
|
|
Überlauf
|
+----------------------------------------------+
Der Knoten wird geteilt:
Die vorderen Schlüssel verbleiben im alten Knoten, der Schlüssel mit der Nummer M+1 gelangt als
Trennschlüssel in den Vorgängerknoten. Die M Schlüssel mit den Nummern M+2 bis 2 ⋅ M + 1
kommen in den neuen Knoten.
+-----------------------------+
| ....S X-1Z X-1S M+1Z YS XZ X .... |
+-----------------------------+
+------------------+
|Z 0S 1 .... Z M-1S MZ M|
+------------------+
+-----------------------------+
|Z M+1S M+2Z M+2 ..... S2M+1Z 2M+1 |
+-----------------------------+
Die geteilten Knoten enthalten genau M Elemente. Das Einfügen eines Elements in der
vorangehenden Seite kann diese ebenfalls zum Überlaufen bringen und somit die Aufteilung
fortsetzen. Der B-Baum wächst demnach von den Blättern bis zur Wurzel.
/*
*Einfügen eines neuen Schlüssels. Rückgabe ist –1, falls
4
Algorithmen und Datenstrukturen
* es misslingt, anderenfalls 0
* Parameter: value
einzufuegender Wert
*/
public int Insert(Integer value)
{
if(root == null)
{
root = new CBNode(MAERER);
root.key.setElementAt((Object)value, 0);
root.count = 1;
} // end if
else
{
if(searchkey(((Integer)value).intValue()) == true)
{
//System.out.println("double key found and will be ignored!");
return -1;
} // end if
CBNode result;
result = insrekurs(root, value);
if(result != null)
{
CBNode node = new CBNode(MAERER);
node.key.setElementAt(newValue, 0);
node.nodeptr.setElementAt(root, 0);
node.nodeptr.setElementAt(result, 1);
node.count = 1;
root = node;
}
// end if(result)
}
// end else
mpCVisualizeTree.DeleteRootKnot();
mpCExtendedCanvas.repaint();
rootflag = 0;
this.drawTree(root);
mpCExtendedCanvas.repaint();
return 0;
}
// end Insert() Methode
Die Methode „Insert“ ruft „insrekurs() “ auf. Diese rekursive Methode leistet die eigentliche Arbeit
/*
* der neue Wert wird rekursiv in den Baum eingebracht
*/
protected CBNode insrekurs(CBNode tempnode, Integer insValue)
{
CBNode result;
result = null;
newValue = insValue;
if(tempnode.nodeptr.elementAt(0) != null) // kein Blatt -> Rekursion
{
int pos = 0;
while(pos < tempnode.count && newValue.intValue() >
((Integer)tempnode.key.elementAt(pos)).intValue())
{
pos++;
} // end while
result = insrekurs((CBNode)tempnode.nodeptr.elementAt(pos), newValue);
if(result == null)
{
return null; // if result = null: nothing has to be inserted into
// node-> finished!
} // end if(resul == null)
5
Algorithmen und Datenstrukturen
} // end if(tempnode.nodeptr.elementAt(0) != null)
// insert a element
CBNode node = null;
int flag = 0;
int s = tempnode.count;
if(s >= MAERER - 1)
// split the knot
{
tempnode.count = (MAERER - 1) / 2;
node = new CBNode(MAERER);
node.count = (MAERER - 1) / 2;
for(int d = ((MAERER - 1) / 2); d > 0;)
{
if(flag != 0 || ((Integer)tempnode.key.elementAt(s - 1)).intValue() >
newValue.intValue())
{
node.nodeptr.setElementAt(tempnode.nodeptr.elementAt(s), d);
node.key.setElementAt(tempnode.key.elementAt(--s), --d);
} // end if(flag != 0 ...
else
{
node.nodeptr.setElementAt(result, d);
node.key.setElementAt(newValue, --d);
flag = 1;
} // end else
}
// end if(s >= MAERER - 1)
if(flag != 0 || ((Integer)tempnode.key.elementAt(s - 1)).intValue() >
newValue.intValue())
{
node.nodeptr.setElementAt(tempnode.nodeptr.elementAt(s), 0);
} // end if
else
{
node.nodeptr.setElementAt(result, 0);
} // end else
} // end if(s >= MAERER - 1)
else
{
tempnode.count++;
} // end else
// shift
for(; s > 0 && ((Integer)tempnode.key.elementAt(s - 1)).intValue() >
newValue.intValue(); s--)
{
tempnode.nodeptr.setElementAt(tempnode.nodeptr.elementAt(s), s + 1);
tempnode.key.setElementAt(tempnode.key.elementAt(s - 1), s);
} // end for
tempnode.key.setElementAt(newValue, s);
tempnode.nodeptr.setElementAt(result, s + 1);
newValue = (Integer) tempnode.key.elementAt((MAERER - 1) / 2);
return node;
} // end insrekurs() methode
Löschen
Grundsätzlich ist zu unterscheiden:
1. Das zu löschende Element ist in einem Blattknoten
2. Das Element ist nicht in einem Blattknoten enthalten.
In diesem Fall ist es durch eines der benachbarten Elemente zu ersetzen. Entlang des rechts
stehenden Zeigers Z ist hier zum Blattknoten hinabzusteigen und das zu löschende Element durch
das äußere linke Element von Z zu ersetzen.
6
Algorithmen und Datenstrukturen
Auf jeden Fall darf die Anzahl der Schlüssel im Knoten nicht kleiner als M werden.
/*
* loescht einen Schlüssel. Rückgabe ist
* anderenfalls 0.
*
* Parameter: zu löschender Wert
*/
public int Delete(Integer delValue)
-1, falls es misslingt;
{
mpCVisualizeTree.MoveToRoot();
if(searchkey(((Integer)delValue).intValue()) == false)
{
return -1;
} // end if
if(delrekurs(root, delValue) == 0)
{
CBNode temp = root;
root = (CBNode)root.nodeptr.elementAt(0);
temp = null;
} // end if
mpCVisualizeTree.DeleteRootKnot();
mpCExtendedCanvas.repaint();
rootflag = 0;
this.drawTree(root);
mpCExtendedCanvas.repaint();
return 0;
} // end Delete() Methode
Die eigentliche Arbeit beim Löschen übernimmt die rekursive Methode „delrekurs()“
/*
* deletes the value rekursively from the tree.
*
*/
private int delrekurs(CBNode delNode, Integer value)
{
int result = 0, pos, found = 0;
Vector nullVec = new Vector();
nullVec = null;
if(delNode != null)
{
CBNode node;
for(pos = 0; pos < delNode.count; pos++)
{
if(value.intValue() <=
((Integer)delNode.key.elementAt(pos)).intValue())
{
if(value.intValue() <
((Integer)delNode.key.elementAt(pos)).intValue())
{
result = delrekurs((CBNode)delNode.nodeptr.elementAt(pos),
(Integer)value);
} // end if
else
{
if(delNode.nodeptr.elementAt(0) == null)
// leaf node!
{
for(; (pos + 1) < delNode.count; pos++)
7
Algorithmen und Datenstrukturen
{
delNode.key.setElementAt(delNode.key.elementAt(pos + 1), pos);
} // end for
//System.out.println("Ende weil Blatt!");
return --delNode.count;
} // end if
else
{
node = (CBNode)delNode.nodeptr.elementAt(pos + 1);
while(node.nodeptr.elementAt(0) != null)
{
node = (CBNode)node.nodeptr.elementAt(0);
} // end while
delNode.key.setElementAt(node.key.elementAt(0), pos);
//System.out.println("Tausch, loesche rechts");
pos++;
result = delrekurs((CBNode)delNode.nodeptr.elementAt(pos),
(Integer)delNode.key.elementAt(pos - 1));
} // end else
} // end else
found = 1;
break;
} // end if
} // end for
if(found == 0)
{
result = delrekurs((CBNode)delNode.nodeptr.elementAt(pos),
(Integer)value);
} // end if
if(result < ((MAERER - 1) / 2))
{
CBNode temp;
int l = 0, r = 0;
if(pos > 0)
{
l = ((CBNode)delNode.nodeptr.elementAt(pos - 1)).count;
} // end if
if(pos < delNode.count)
{
r = ((CBNode)delNode.nodeptr.elementAt(pos + 1)).count;
} // end if
node = (CBNode)delNode.nodeptr.elementAt(pos);
if(l > (MAERER - 1) / 2)
// steal a key from left
{
//System.out.println("klaue einen Schluessel von links");
temp = (CBNode)delNode.nodeptr.elementAt(pos - 1);
for(int i = node.count; i > 0; i--)
{
node.key.setElementAt(node.key.elementAt(i - 1), i);
node.nodeptr.setElementAt(node.nodeptr.elementAt(i), i + 1);
} // end for
node.nodeptr.setElementAt(node.nodeptr.elementAt(0), 1);
node.count++;
node.key.setElementAt(delNode.key.elementAt(pos - 1), 0);
node.nodeptr.setElementAt(temp.nodeptr.elementAt(temp.count), 0);
delNode.key.setElementAt(temp.key.elementAt(--temp.count), pos - 1);
} // end if
else
{
if(r > (MAERER - 1) / 2)
// steal a key from right
{
// System.out.println("klaue Schluessel von rechts");
temp = (CBNode)delNode.nodeptr.elementAt(pos + 1);
8
Algorithmen und Datenstrukturen
node.key.setElementAt(delNode.key.elementAt(pos), node.count);
node.count++;
node.nodeptr.setElementAt(temp.nodeptr.elementAt(0), node.count);
delNode.key.setElementAt(temp.key.elementAt(0), pos);
for(int i = 1; i < temp.count; i++)
{
temp.key.setElementAt(temp.key.elementAt(i), i - 1);
temp.nodeptr.setElementAt(temp.nodeptr.elementAt(i), i - 1);
} // end for
temp.nodeptr.setElementAt(temp.nodeptr.elementAt(temp.count),
temp.count - 1);
temp.count--;
} // end if
else
{
//System.out.println("Knoten verschmelzen !");
if(r == 0)
{
pos--;
} // end if
node = (CBNode)delNode.nodeptr.elementAt(pos);
temp = (CBNode)delNode.nodeptr.elementAt(pos + 1);
node.key.setElementAt(delNode.key.elementAt(pos),
node.count++);
node.nodeptr.setElementAt(temp.nodeptr.elementAt(0), node.count);
for(int i = 0; i < temp.count; i++)
{
node.key.setElementAt(temp.key.elementAt(i), node.count++);
node.nodeptr.setElementAt(temp.nodeptr.elementAt(i + 1),
node.count);
} // end for
// System.out.println(
//
"Jetzt kann der Knoten rechts daneben entfernt werden!");
delNode.count--;
// delNode.nodeptr.elementAt(pos + 1) = null; // geht das so?
delNode.nodeptr.setElementAt((Object)nullVec, pos + 1);
while(pos < delNode.count)
{
delNode.key.setElementAt(delNode.key.elementAt(pos + 1), pos);
pos++;
delNode.nodeptr.setElementAt(delNode.nodeptr.elementAt(pos + 1),
pos);
} // end while
} // end else
} // end else
} // end if
return delNode.count;
} // end if
else
{
return 0;
} // end else
} // end delrekurs() Methode
9
Algorithmen und Datenstrukturen
Lösung:
CBNode.java
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
=======================================================================
Project to the course OP
WS1998/99
Fachhochschule Regensburg
Filename: CBNode.java
Author : Hr. Thomas Dotzler
Version : 2 .1.4.2
Date
: 01/06/1999
last modified: 01/20/199
reason: source code documentation
Task:
This file contains the source code for the implementation of a node
balanced tree JAVA.
To see what the methods are performing, refer to the project
documentation.
compile with (JDK-1.1.7): javac CBNode.java
// ========================================================================
import java.util.*;
/*
* The CBNode class represents on single Node of the Bayer Tree.
*/
public class CBNode
{
protected Vector key, nodeptr, initkey, initvec;
int count;
/*
* constructs a single Bayer Tree node with M references to subnodes.
*/
CBNode(int M)
{
// System.out.println("CBNode(): constructor invoked!");
nodeptr = new Vector();
initvec = new Vector();
initvec = null;
key = new Vector();
initkey = new Vector();
initkey = null;
for(int i = 0; i <= M; i++)
{
nodeptr.addElement((Object)initvec);
// System.out.println(i + "ter Nodepointer erzeugt. Wert: " +
//
nodeptr.elementAt(i));
}
for(int j = 0; j <= M - 1; j++)
{
key.addElement((Object)initkey);
// System.out.println(j + "ter Key erzeugt. Wert: " +
key.elementAt(j));
}
count = 0;
// System.out.println("count Wert: " + count);
}
}
CBayerTree.java
// ========================================================================
10
Algorithmen und Datenstrukturen
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
Project to the course OP WS1998/99
Fachhochschule Regensburg
Filename: CBayerTree.java
Author : Hr. Thomas Dotzler, Hr. Thomas Feldbauer,
who helped me out with the algorithm in C++
Version : 2.1.4.2
Date
: 01/06/1999
last modified: 01/20/199
reason: source code documentation
Task:
This file contains the source code for the implementation of a balanced
tree in JAVA. The essential methods are:
public int Insert(Integer value)
public int Delete(Integer delValue)
compile with (JDK-1.1.7): javac CBayerTree.java
====================================================================
import java.util.*;
import java.lang.*;
/*
* The Class CBayerTree has been designed to represent a balanced
* or a so called "Bayer" Tree.
* It is implemented to build up trees with different orders where the
*order is represented
*/
class CBayerTree
{
// protected class parameter
/*
* The variable <b>MAERER</b> defines the order of the balanced tree.
* It also defines how many
* subnodes or subtrees each node can have (max.
* MAERER). Each node consists of MAERER pointer
* to subnodes and MAERER - 1 data fields.
*/
protected int MAERER = 5;
/*
* contains the reference to the CVisualizeTree class. It will be set in
* the constructor.
*/
protected CVisualizeTree mpCVisualizeTree;
/*
* contains the reference to the CExtendedCanvas class. It will be set in
* the constructor.
*/
protected CExtendedCanvas mpCExtendedCanvas;
/*
* references to the root node as long as the tree existsts.
*/
protected CBNode root;
/*
*is used to store the new value that will be inserted into the balanced
11
Algorithmen und Datenstrukturen
* tree.
*/
protected Integer newValue;
/*
* indicates the root node.
*/
private int rootflag = 0;
//
/*
*
*
*
*/
class constructor
Constructs an empty balanced tree.
Parameter: pCExtendedCanvas
the reference to CExtendedCanvas class.
Parameter: pVisualizeTree
the reference to CVisualizeTree class.
public CBayerTree(CExtendedCanvas pCExtendedCanvas,
CVisualizeTree pCVisualizeTree)
{
root = null;
mpCVisualizeTree = pCVisualizeTree;
mpCExtendedCanvas = pCExtendedCanvas;
ResetTreeWithOrder(MAERER);
} // end constructor
// public functions
/*
* inserts a new Value into the tree. Returns -1 if it fails to insert a
* value otherwise 0.
*
* Parameter: value
the value to be inserted wrapped by an
*
<i>Integer</i> object.
*/
public int Insert(Integer value)
{
if(root == null)
{
root = new CBNode(MAERER);
root.key.setElementAt((Object)value, 0);
root.count = 1;
} // end if
else
{
if(searchkey(((Integer)value).intValue()) == true)
{
//System.out.println("double key found and will be ignored!");
return -1;
} // end if
CBNode result;
result = insrekurs(root, value);
if(result != null)
{
CBNode node = new CBNode(MAERER);
node.key.setElementAt(newValue, 0);
node.nodeptr.setElementAt(root, 0);
node.nodeptr.setElementAt(result, 1);
node.count = 1;
root = node;
}
// end if(result)
}
// end else
mpCVisualizeTree.DeleteRootKnot();
12
Algorithmen und Datenstrukturen
mpCExtendedCanvas.repaint();
rootflag = 0;
this.drawTree(root);
mpCExtendedCanvas.repaint();
return 0;
}
// end Insert() Methode
/*
* deletes a value from the tree. Returns -1 if it fails to delete the
* value otherwise 0.
*
* Parameter: delValue the value to be deleted wrapped by an
* Integer-Object
*/
public int Delete(Integer delValue)
{
mpCVisualizeTree.MoveToRoot();
if(searchkey(((Integer)delValue).intValue()) == false)
{
return -1;
} // end if
if(delrekurs(root, delValue) == 0)
{
CBNode temp = root;
root = (CBNode)root.nodeptr.elementAt(0);
temp = null;
} // end if
mpCVisualizeTree.DeleteRootKnot();
mpCExtendedCanvas.repaint();
rootflag = 0;
this.drawTree(root);
mpCExtendedCanvas.repaint();
return 0;
} // end Delete() Methode
/*
* is used to search a key in the tree. Returns true if the key was found
* otherwise false.
*/
public boolean searchkey(int key)
{
boolean found = false;
int i = 0, n;
CBNode node = root;
while(node != null)
{
i = 0;
n = node.count;
// search key in actual node
while(i < n && key > ((Integer)node.key.elementAt(i)).intValue())
{
i++;
}
// end while
if(i < n && key == ((Integer)node.key.elementAt(i)).intValue())
{
found = true;
}
if(node.nodeptr.elementAt(i) != null)
{
mpCVisualizeTree.MoveLevelDown(i);
}
node = (CBNode) node.nodeptr.elementAt(i);
}
// end while (node != null)
13
Algorithmen und Datenstrukturen
return found;
}
// end searchkey Methode
/*
* resets the tree and initializes the tree with the new order
* Parameter
order
the order of the tree
*/
public void ResetTreeWithOrder(int order)
{
mpCVisualizeTree.DeleteRootKnot();
mpCVisualizeTree.SetNumberOfPointers(order);
mpCExtendedCanvas.repaint();
root = null;
MAERER = order;
} // end ResetTreeWithOrder() Methode
// protected functions
/*
* inserts the new value rekursively into the tree.
*/
protected CBNode insrekurs(CBNode tempnode, Integer insValue)
{
CBNode result;
result = null;
newValue = insValue;
if(tempnode.nodeptr.elementAt(0) != null)
// not a leaf -> rekurs
{
int pos = 0;
while(pos < tempnode.count && newValue.intValue() >
((Integer)tempnode.key.elementAt(pos)).intValue())
{
pos++;
} // end while
result = insrekurs((CBNode)tempnode.nodeptr.elementAt(pos), newValue);
if(result == null)
{
return null; // if result = null: nothing has to be inserted into
// node-> finished!
} // end if(resul == null)
} // end if(tempnode.nodeptr.elementAt(0) != null)
// insert a element
CBNode node = null;
int flag = 0;
int s = tempnode.count;
if(s >= MAERER - 1)
// split the knot
{
tempnode.count = (MAERER - 1) / 2;
node = new CBNode(MAERER);
node.count = (MAERER - 1) / 2;
for(int d = ((MAERER - 1) / 2); d > 0;)
{
if(flag != 0 || ((Integer)tempnode.key.elementAt(s - 1)).intValue() >
newValue.intValue())
{
node.nodeptr.setElementAt(tempnode.nodeptr.elementAt(s), d);
node.key.setElementAt(tempnode.key.elementAt(--s), --d);
} // end if(flag != 0 ...
else
{
node.nodeptr.setElementAt(result, d);
node.key.setElementAt(newValue, --d);
flag = 1;
} // end else
}
// end if(s >= MAERER - 1)
if(flag != 0 || ((Integer)tempnode.key.elementAt(s - 1)).intValue() >
14
Algorithmen und Datenstrukturen
newValue.intValue())
{
node.nodeptr.setElementAt(tempnode.nodeptr.elementAt(s), 0);
} // end if
else
{
node.nodeptr.setElementAt(result, 0);
} // end else
} // end if(s >= MAERER - 1)
else
{
tempnode.count++;
} // end else
// shift
for(; s > 0 && ((Integer)tempnode.key.elementAt(s - 1)).intValue() >
newValue.intValue(); s--)
{
tempnode.nodeptr.setElementAt(tempnode.nodeptr.elementAt(s), s + 1);
tempnode.key.setElementAt(tempnode.key.elementAt(s - 1), s);
} // end for
tempnode.key.setElementAt(newValue, s);
tempnode.nodeptr.setElementAt(result, s + 1);
newValue = (Integer) tempnode.key.elementAt((MAERER - 1) / 2);
return node;
} // end insrekurs() methode
/*
* deletes the value rekursively from the tree.
*
*/
private int delrekurs(CBNode delNode, Integer value)
{
int result = 0, pos, found = 0;
Vector nullVec = new Vector();
nullVec = null;
if(delNode != null)
{
CBNode node;
for(pos = 0; pos < delNode.count; pos++)
{
if(value.intValue() <=
((Integer)delNode.key.elementAt(pos)).intValue())
{
if(value.intValue() <
((Integer)delNode.key.elementAt(pos)).intValue())
{
result = delrekurs((CBNode)delNode.nodeptr.elementAt(pos),
(Integer)value);
} // end if
else
{
if(delNode.nodeptr.elementAt(0) == null)
// leaf node!
{
for(; (pos + 1) < delNode.count; pos++)
{
delNode.key.setElementAt(delNode.key.elementAt(pos + 1), pos);
} // end for
//System.out.println("Ende weil Blatt!");
return --delNode.count;
} // end if
else
{
node = (CBNode)delNode.nodeptr.elementAt(pos + 1);
15
Algorithmen und Datenstrukturen
while(node.nodeptr.elementAt(0) != null)
{
node = (CBNode)node.nodeptr.elementAt(0);
} // end while
delNode.key.setElementAt(node.key.elementAt(0), pos);
//System.out.println("Tausch, loesche rechts");
pos++;
result = delrekurs((CBNode)delNode.nodeptr.elementAt(pos),
(Integer)delNode.key.elementAt(pos - 1));
} // end else
} // end else
found = 1;
break;
} // end if
} // end for
if(found == 0)
{
result = delrekurs((CBNode)delNode.nodeptr.elementAt(pos),
(Integer)value);
} // end if
if(result < ((MAERER - 1) / 2))
{
CBNode temp;
int l = 0, r = 0;
if(pos > 0)
{
l = ((CBNode)delNode.nodeptr.elementAt(pos - 1)).count;
} // end if
if(pos < delNode.count)
{
r = ((CBNode)delNode.nodeptr.elementAt(pos + 1)).count;
} // end if
node = (CBNode)delNode.nodeptr.elementAt(pos);
if(l > (MAERER - 1) / 2)
// steal a key from left
{
//System.out.println("klaue einen Schluessel von links");
temp = (CBNode)delNode.nodeptr.elementAt(pos - 1);
for(int i = node.count; i > 0; i--)
{
node.key.setElementAt(node.key.elementAt(i - 1), i);
node.nodeptr.setElementAt(node.nodeptr.elementAt(i), i + 1);
} // end for
node.nodeptr.setElementAt(node.nodeptr.elementAt(0), 1);
node.count++;
node.key.setElementAt(delNode.key.elementAt(pos - 1), 0);
node.nodeptr.setElementAt(temp.nodeptr.elementAt(temp.count), 0);
delNode.key.setElementAt(temp.key.elementAt(--temp.count), pos - 1);
} // end if
else
{
if(r > (MAERER - 1) / 2)
// steal a key from right
{
// System.out.println("klaue Schluessel von rechts");
temp = (CBNode)delNode.nodeptr.elementAt(pos + 1);
node.key.setElementAt(delNode.key.elementAt(pos), node.count);
node.count++;
node.nodeptr.setElementAt(temp.nodeptr.elementAt(0), node.count);
delNode.key.setElementAt(temp.key.elementAt(0), pos);
for(int i = 1; i < temp.count; i++)
{
temp.key.setElementAt(temp.key.elementAt(i), i - 1);
temp.nodeptr.setElementAt(temp.nodeptr.elementAt(i), i - 1);
16
Algorithmen und Datenstrukturen
} // end for
temp.nodeptr.setElementAt(temp.nodeptr.elementAt(temp.count),
temp.count - 1);
temp.count--;
} // end if
else
{
//System.out.println("Knoten verschmelzen !");
if(r == 0)
{
pos--;
} // end if
node = (CBNode)delNode.nodeptr.elementAt(pos);
temp = (CBNode)delNode.nodeptr.elementAt(pos + 1);
node.key.setElementAt(delNode.key.elementAt(pos),
node.count++);
node.nodeptr.setElementAt(temp.nodeptr.elementAt(0), node.count);
for(int i = 0; i < temp.count; i++)
{
node.key.setElementAt(temp.key.elementAt(i), node.count++);
node.nodeptr.setElementAt(temp.nodeptr.elementAt(i + 1),
node.count);
} // end for
// System.out.println(
//
"Jetzt kann der Knoten rechts daneben entfernt werden!");
delNode.count--;
// delNode.nodeptr.elementAt(pos + 1) = null; // geht das so?
delNode.nodeptr.setElementAt((Object)nullVec, pos + 1);
while(pos < delNode.count)
{
delNode.key.setElementAt(delNode.key.elementAt(pos + 1), pos);
pos++;
delNode.nodeptr.setElementAt(delNode.nodeptr.elementAt(pos + 1),
pos);
} // end while
} // end else
} // end else
} // end if
return delNode.count;
} // end if
else
{
return 0;
} // end else
} // end delrekurs() Methode
/*
* deletes the visualized Tree
*/
protected void delTree(CBNode rootNode)
{
if(rootflag == 0)
{
for(int k = 0; k < rootNode.count; k++)
{
mpCVisualizeTree.DeleteKnotValue(k);
mpCExtendedCanvas.repaint();
} // end for(int k = 0; k < rootNode.count; k++)
rootflag = 1;
} // end if(rootflag == 0)
if(rootNode != null)
{
for(int i = 0; i < rootNode.count; i++)
{
17
Algorithmen und Datenstrukturen
if(rootNode.nodeptr.elementAt(i) != null)
{
mpCVisualizeTree.MoveLevelDown(i);
} // end if
delTree((CBNode)rootNode.nodeptr.elementAt(i));
mpCVisualizeTree.DeleteKnotValue(i);
mpCExtendedCanvas.repaint();
} // end if
if(rootNode.nodeptr.elementAt(rootNode.count) != null)
{
mpCVisualizeTree.MoveLevelDown(rootNode.count);
}
// end if
delTree((CBNode)rootNode.nodeptr.elementAt(rootNode.count));
mpCVisualizeTree.MoveLevelUp();
for(int k = 0; k < rootNode.count + 1; k++)
{
mpCVisualizeTree.DeleteSubKnot(k);
mpCExtendedCanvas.repaint();
} // end for
}
// end if(rootNode != null)
} // end delTree() Methode
/*
* draws the tree.
*/
protected void drawTree(CBNode rootNode)
{
if(rootNode != null)
{
if(rootflag == 0)
{
mpCVisualizeTree.CreateRootKnot();
mpCVisualizeTree.InsertKnotValue(0,
((Integer)rootNode.key.elementAt(0)).intValue());
rootflag = 1;
}
// end if(rootflag == 0)
for(int i = 0; i < rootNode.count; i++)
{
if(rootNode.nodeptr.elementAt(i) != null)
{
//System.out.println(
// "create SubKnot at pos: " + i + " and move down same pos");
mpCVisualizeTree.InsertNewSubKnot(i);
mpCVisualizeTree.MoveLevelDown(i);
} // end if
drawTree((CBNode)rootNode.nodeptr.elementAt(i));
// System.out.println("insert element: " + rootNode.key.elementAt(i) +
//
" at pos: " + i);
mpCVisualizeTree.InsertKnotValue(i,
((Integer)rootNode.key.elementAt(i)).intValue());
} // end for
if(rootNode.nodeptr.elementAt(rootNode.count) != null)
{
//System.out.println("create SubKnot at pos: " + rootNode.count +
// " and move down same pos");
mpCVisualizeTree.InsertNewSubKnot(rootNode.count);
mpCVisualizeTree.MoveLevelDown(rootNode.count);
}
// end if
drawTree((CBNode)rootNode.nodeptr.elementAt(rootNode.count));
//System.out.println("move level up");
mpCVisualizeTree.MoveLevelUp();
}
// end if(rootNode != null)
} // end drawTree() Methode
/*
18
Algorithmen und Datenstrukturen
* shows the keys in the tree in a in-order run. For test purpose only.
*/
private void showrekurs(CBNode rootNode)
{
if(rootNode != null)
{
for(int i = 0; i < rootNode.count; i++)
{
showrekurs((CBNode)rootNode.nodeptr.elementAt(i));
System.out.print(rootNode.key.elementAt(i) + " ");
} // end for
showrekurs((CBNode)rootNode.nodeptr.elementAt(rootNode.count));
} // end if
} // end showrekurs() Methode
} // End Class CBTree
19
Herunterladen