AuD
Lecture 'Algorithmen und Datenstrukturen' (code examples)
KTreeNode.java
Go to the documentation of this file.
1package aud;
2
6import aud.util.Sys;
7
47public class KTreeNode<Key extends Comparable<Key> >
49
54 protected class Entry {
55 Entry(Key key,KTreeNode<Key> child) {
56 this.key=key;
57 this.child=child;
58 }
59 Entry(Entry other) {
60 this.key=other.key;
61 this.child=other.child;
62 }
63 final Key key;
64 KTreeNode<Key> child;
65
66 @Override public String toString() {
67 return key!=null ? key.toString() : "null";
68 }
69 }
70
71 KTreeNode<Key> parent_ = null;
72 Vector<Entry> entries_;
73
76 protected int compareKeys(Key a,Key b) {
77 if (a==null) return -1;
78 if (b==null) return +1;
79 else return a.compareTo(b);
80 }
81
85 public KTreeNode() {
86 entries_=new Vector<Entry>();
87 entries_.push_back(new Entry(null,null)); // left child with key null
88 }
89
91 public KTreeNode(Key key) {
92 entries_=new Vector<Entry>();
93 entries_.push_back(new Entry(null,null)); // left child with key null
94 entries_.push_back(new Entry(key,null));
95 }
97 public int getK() { return entries_.size(); }
98
103 public Key getKey(int k) {
104 assert(0<k && k<getK());
105 return entries_.at(k).key;
106 }
107
112 public KTreeNode<Key> getChild(int k) {
113 assert(0<=k && k<getK());
114 return entries_.at(k).child;
115 }
116
122 public Key find(Key key) {
123 for (int i=1;i<entries_.size();++i) {
124 int cmp=compareKeys(key,entries_.at(i).key);
125 if (cmp==0)
126 return entries_.at(i).key;
127 else if (cmp<0) {
128 if (entries_.at(i-1).child==null)
129 return null;
130 else
131 return entries_.at(i-1).child.find(key);
132 }
133 }
134 return entries_.back().child!=null ? entries_.back().child.find(key) : null;
135 }
136
141 int getIndexOfChild(KTreeNode<Key> child) {
142 assert(child!=null);
143 for (int i=0;i<entries_.size();++i)
144 if (entries_.at(i).child==child)
145 return i;
146 return -1;
147 }
148
155 Entry insert(Key key,int k) {
156 assert(key!=null);
157 assert(0<=k && k<=getK()); // unchecked
158
159 Entry entry=new Entry(key,null);
160 entries_.insert(k+1,entry);
161
162 assert(entries_.at(k+1)==entry);
163 assert(k==0 || compareKeys(entries_.at(k-1).key,key)<0);
164 assert(k+2>=getK() || compareKeys(key,entries_.at(k+2).key)<0);
165
166 return entry;
167 }
168
175 void split(int k) {
176 assert(1<k && k<getK()-1);
177 KTreeNode<Key> tmpRoot=new KTreeNode<Key>(getKey(k));
178 // note: tmpRoot is never used as a node, we "steal" its entries below
179
180 KTreeNode<Key> left=new KTreeNode<Key>(getKey(1));
181 left.entries_.at(0).child=entries_.at(0).child;
182 left.entries_.at(1).child=entries_.at(1).child; // left
183 for (int i=2;i<k;++i)
184 left.entries_.push_back(entries_.at(i));
185 tmpRoot.entries_.front().child=left;
186 left.updateChildrensParent();
187
188 KTreeNode<Key> right=new KTreeNode<Key>(getKey(k+1));
189 right.entries_.at(0).child=entries_.at(k).child;
190 right.entries_.at(1).child=entries_.at(k+1).child; // right
191 for (int i=k+2;i<getK();++i)
192 right.entries_.push_back(entries_.at(i));
193 tmpRoot.entries_.back().child=right;
194 right.updateChildrensParent();
195
196 // steal entries_ from tmpRoot, parent remains same
197 this.entries_=tmpRoot.entries_;
198 left.parent_=right.parent_=this;
199 }
200
205 void mergeChild(int k) {
206 KTreeNode<Key> child=getChild(k);
207 assert(child!=null);
208
209 // insert entries of child
210 for (int i=child.getK()-1;i>0;--i)
211 entries_.insert(k+1,child.entries_.at(i));
212
213 // update their parent reference
214 for (int i=0;i<child.getK();++i)
215 if (child.entries_.at(i).child!=null) {
216 assert(child.entries_.at(i).child.parent_==child);
217 child.entries_.at(i).child.parent_=this;
218 }
219
220 entries_.at(k).child=child.entries_.at(0).child;
221 }
222
224 private void updateChildrensParent() {
225 for (Entry e : entries_) {
226 if (e.child!=null)
227 e.child.parent_=this;
228 }
229 }
230
234 public void checkConsistency() {
235 if (parent_!=null) {
236 int i=parent_.getIndexOfChild(this);
237 if (i<0)
238 throw new RuntimeException("parent-child mismatch");
239 }
240 for (int i=0; i<entries_.size(); ++i) {
241 if (entries_.at(i).child!=null) {
242 if (entries_.at(i).child.parent_!=this)
243 throw new RuntimeException("invalid parent");
244 }
245 if (i>1) {
246 if (compareKeys(entries_.at(i-1).key,entries_.at(i).key)>=0) {
247 throw new RuntimeException("invalid order of entries");
248 }
249 }
250 // missing: check if children's keys fit in
251
252 if (entries_.at(i).child!=null)
253 entries_.at(i).child.checkConsistency();
254 }
255 }
256
257 @Override public String toString() {
258 java.util.Iterator<Entry> ii=entries_.iterator();
259 assert(ii.hasNext());
260 Entry entry=ii.next();
261 assert(entry.key==null);
262 String rv="";
263 while (ii.hasNext()) {
264 rv+=ii.next().toString();
265 if (ii.hasNext())
266 rv+=" | ";
267 }
268 return rv;
269 }
270
271 @Override public GraphvizDecorator getDecorator() {
272 return null;
273 }
274
275 @Override public String toDot() {
276 String dot="graph BinaryTree {\n";
277
278 GraphvizDecorator decorator=getDecorator();
279 if (decorator!=null) {
280 String d=decorator.getGlobalStyle();
281 if (d!=null) dot+=" "+d+";\n";
282 d=decorator.getGraphDecoration(this);
283 if (d!=null) dot+=" graph ["+d+"];\n";
284 }
285 dot+=treeToDot(null);
286
287 dot+="\n}\n";
288 //System.out.println(dot);
289 return dot;
290 }
291
292 private String dotRef() {
293 return toString()+"-"+hashCode();
294 }
295
296 protected String dotLabel() { return toString(); }
297
298 private String treeToDot(KTreeNode<Key> parent) {
299 // Currently no "root" or "same rank" tags. Do we require them?
300
301 GraphvizDecorator decorator=getDecorator();
302 String dot =" \""+dotRef()+"\" [label=\""+dotLabel()+"\",";
303 dot+=(decorator!=null) ? decorator.getFullNodeDecoration(this) : "shape=box";
304 dot+="];\n";
305
306 int k=0;
307 for (Entry entry : entries_) {
308 if (entry.child!=null)
309 dot+=entry.child.treeToDot(this);
310 else
311 dot+=dotLeaf("-"+k);
312 ++k;
313 }
314
315 dot+="\n";
316
317 if (parent!=null) { // edge is identified by "lower" node
318 dot+=" \""+parent.dotRef()+"\" -- \""+
319 dotRef()+"\" ["; // no edge labels currently
320 dot+=(decorator!=null) ? decorator.getFullEdgeDecoration(this) : "";
321 dot+="];\n";
322 }
323
324 return dot;
325 }
326
328 private String dotLeaf(String side) {
329 String dummy="\""+dotRef()+"-"+side+"\"";
330 String dot=" "+dummy+" [shape=point];\n";
331 dot+=" \""+dotRef()+"\" -- "+dummy+" [];\n";
332 return dot;
333 }
334
336 public String toTikZ() {
337 return "\\"+toTikZ(0)+";\n";
338 }
339 protected String tikzNodeStyle() { return ""; }
340 protected String toTikZ(int level) {
341 String spaces=Sys.indent(level);
342 String tex=spaces+"node "+tikzNodeStyle()+" {"+toString()+"}\n";
343
344 int k=0;
345 for (Entry entry : entries_) {
346 if (entry.child!=null)
347 tex+=spaces+" child {\n"+entry.child.toTikZ(level+1)+" }\n";
348 // else
349 ++k;
350 }
351
352 return tex;
353 }
354
355 public static void main(String[] args) {
356 KTreeNode<String> node=new KTreeNode<String>("a");
357 node.insert("b",1);
358 node.insert("c",2);
359 node.insert("d",3);
360 node.insert("e",4);
361
362 System.out.println(node.find("b"));
363 System.out.println(node.find("d"));
364 System.out.println(node.find("x"));
365
366 //String dot=node.toDot();
367 //System.out.println(dot);
368 aud.util.DotViewer.displayWindow(node,"KTreeNode");
369
370 node.split(3);
371 //System.out.println(dot=node.toDot());
372 aud.util.DotViewer.displayWindow(node,"KTreeNode split");
373
374 System.out.println(node.find("b"));
375 System.out.println(node.find("d"));
376 System.out.println(node.find("x"));
377
378 System.out.println(node.toTikZ());
379
380 node.mergeChild(0);
381 //System.out.println(dot=node.toDot());
382 aud.util.DotViewer.displayWindow(node,"KTreeNode merge 0");
383
384 System.out.println(node.find("b"));
385 System.out.println(node.find("d"));
386 System.out.println(node.find("x"));
387
388 node.mergeChild(3);
389 //System.out.println(dot=node.toDot());
390 aud.util.DotViewer.displayWindow(node,"KTreeNode merge 3"); // FIXME
391
392 System.out.println(node.find("b"));
393 System.out.println(node.find("d"));
394 System.out.println(node.find("x"));
395
396 node.checkConsistency();
397 }
398}
Entry in a KTreeNode with reference to key and left child.
Definition: KTreeNode.java:54
Implementation of an array-based vector.
Definition: Vector.java:44
Simple viewer for Graphvizable.
Definition: DotViewer.java:48
static DotViewer displayWindow(Graphvizable object, String caption)
create new DotViewer (toplevel window) and display object
Definition: DotViewer.java:140
Decorator for items of Graphvizable objects.
System related utilities.
Definition: Sys.java:58
Interface for decorating items of Graphvizable objects.
Interface for GraphViz rendering.
utilities (not related to AuD lecture)
Definition: Colormap.java:1
AuD lecture: Data structures, algorithms, examples.
Definition: A234Tree.java:1