1
2
3
4
5
6
7
8
9
10
11
12 package edu.uci.ics.jung.graph;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashMap;
18 import java.util.List;
19 import java.util.Map;
20
21 import com.google.common.base.Supplier;
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.ImmutableSet;
24
25 import edu.uci.ics.jung.graph.util.EdgeType;
26 import edu.uci.ics.jung.graph.util.Pair;
27
28
29
30
31
32
33
34
35
36 @SuppressWarnings("serial")
37 public class OrderedKAryTree<V, E> extends AbstractTypedGraph<V, E> implements Tree<V, E>
38 {
39 protected Map<E, Pair<V>> edge_vpairs;
40 protected Map<V, VertexData> vertex_data;
41 protected int height;
42 protected V root;
43 protected int order;
44
45
46
47
48
49
50
51 public static <V,E> Supplier<DirectedGraph<V,E>> getFactory(final int order) {
52 return new Supplier<DirectedGraph<V,E>> () {
53 public DirectedGraph<V,E> get() {
54 return new OrderedKAryTree<V,E>(order);
55 }
56 };
57 }
58
59
60
61
62
63 public OrderedKAryTree(int order)
64 {
65 super(EdgeType.DIRECTED);
66 this.order = order;
67 this.height = -1;
68 this.edge_vpairs = new HashMap<E, Pair<V>>();
69 this.vertex_data = new HashMap<V, VertexData>();
70 }
71
72
73
74
75
76
77 public int getChildCount(V vertex) {
78 if (!containsVertex(vertex))
79 return 0;
80 List<E> edges = vertex_data.get(vertex).child_edges;
81 if (edges == null)
82 return 0;
83 int count = 0;
84 for (E edge : edges)
85 count += edge == null ? 0 : 1;
86
87 return count;
88 }
89
90
91
92
93
94
95
96 public E getChildEdge(V vertex, int index)
97 {
98 if (!containsVertex(vertex))
99 return null;
100 List<E> edges = vertex_data.get(vertex).child_edges;
101 if (edges == null)
102 return null;
103 return edges.get(index);
104 }
105
106
107
108
109 public Collection<E> getChildEdges(V vertex)
110 {
111 if (!containsVertex(vertex))
112 return null;
113 List<E> edges = vertex_data.get(vertex).child_edges;
114 return edges == null ? Collections.<E>emptySet() :
115 new ImmutableList.Builder<E>().addAll(edges).build();
116 }
117
118
119
120
121
122
123
124
125 public Collection<V> getChildren(V vertex)
126 {
127 if (!containsVertex(vertex))
128 return null;
129 List<E> edges = vertex_data.get(vertex).child_edges;
130 if (edges == null)
131 return Collections.emptySet();
132 Collection<V> children = new ArrayList<V>(order);
133 for (E edge : edges)
134 children.add(this.getOpposite(vertex, edge));
135 return new ImmutableList.Builder<V>().addAll(children).build();
136 }
137
138
139
140
141
142
143 public int getDepth(V vertex)
144 {
145 if (!containsVertex(vertex))
146 return -1;
147 return vertex_data.get(vertex).depth;
148 }
149
150
151
152
153
154 public int getHeight()
155 {
156 return height;
157 }
158
159
160
161
162 public V getParent(V vertex)
163 {
164 if (!containsVertex(vertex))
165 return null;
166 else if (vertex.equals(root))
167 return null;
168 return edge_vpairs.get(vertex_data.get(vertex).parent_edge).getFirst();
169 }
170
171
172
173
174 public E getParentEdge(V vertex)
175 {
176 if (!containsVertex(vertex))
177 return null;
178 return vertex_data.get(vertex).parent_edge;
179 }
180
181
182
183
184 public V getRoot()
185 {
186 return root;
187 }
188
189
190
191
192 public Collection<Tree<V, E>> getTrees()
193 {
194 Collection<Tree<V, E>> forest = new ArrayList<Tree<V, E>>(1);
195 forest.add(this);
196 return forest;
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 public boolean addEdge(E e, V parent, V child, int index)
215 {
216 if (e == null || child == null || parent == null)
217 throw new IllegalArgumentException("Inputs may not be null");
218 if (!containsVertex(parent))
219 throw new IllegalArgumentException("Tree must already " +
220 "include parent: " + parent);
221 if (containsVertex(child))
222 throw new IllegalArgumentException("Tree must not already " +
223 "include child: " + child);
224 if (parent.equals(child))
225 throw new IllegalArgumentException("Input vertices must be distinct");
226 if (index < 0 || index >= order)
227 throw new IllegalArgumentException("'index' must be in [0, [order-1]]");
228
229 Pair<V> endpoints = new Pair<V>(parent, child);
230 if (containsEdge(e))
231 if (!endpoints.equals(edge_vpairs.get(e)))
232 throw new IllegalArgumentException("Tree already includes edge" +
233 e + " with different endpoints " + edge_vpairs.get(e));
234 else
235 return false;
236
237 VertexData parent_data = vertex_data.get(parent);
238 List<E> outedges = parent_data.child_edges;
239
240 if (outedges == null)
241 outedges = new ArrayList<E>(this.order);
242
243 boolean edge_placed = false;
244 if (index >= 0)
245 if (outedges.get(index) != null)
246 throw new IllegalArgumentException("Parent " + parent +
247 " already has a child at index " + index + " in this tree");
248 else
249 outedges.set(index, e);
250 for (int i = 0; i < order; i++)
251 {
252 if (outedges.get(i) == null)
253 {
254 outedges.set(i, e);
255 edge_placed = true;
256 break;
257 }
258 }
259 if (!edge_placed)
260 throw new IllegalArgumentException("Parent " + parent + " already" +
261 " has " + order + " children in this tree");
262
263
264 VertexData child_data = new VertexData(e, parent_data.depth + 1);
265 vertex_data.put(child, child_data);
266
267 height = child_data.depth > height ? child_data.depth : height;
268 edge_vpairs.put(e, endpoints);
269
270 return true;
271 }
272
273
274
275
276 @Override
277 public boolean addEdge(E e, V parent, V child)
278 {
279 return addEdge(e, parent, child, -1);
280 }
281
282
283
284
285
286 @Override
287 public boolean addEdge(E e, V v1, V v2, EdgeType edge_type)
288 {
289 this.validateEdgeType(edge_type);
290 return addEdge(e, v1, v2);
291 }
292
293
294
295
296 public V getDest(E directed_edge)
297 {
298 if (!containsEdge(directed_edge))
299 return null;
300 return edge_vpairs.get(directed_edge).getSecond();
301 }
302
303
304
305
306 public Pair<V> getEndpoints(E edge)
307 {
308 if (!containsEdge(edge))
309 return null;
310 return edge_vpairs.get(edge);
311 }
312
313
314
315
316 public Collection<E> getInEdges(V vertex)
317 {
318 if (!containsVertex(vertex))
319 return null;
320 else if (vertex.equals(root))
321 return Collections.emptySet();
322 else
323 return Collections.singleton(getParentEdge(vertex));
324 }
325
326
327
328
329 @Override
330 public V getOpposite(V vertex, E edge)
331 {
332 if (!containsVertex(vertex) || !containsEdge(edge))
333 return null;
334 Pair<V> endpoints = edge_vpairs.get(edge);
335 V v1 = endpoints.getFirst();
336 V v2 = endpoints.getSecond();
337 return v1.equals(vertex) ? v2 : v1;
338 }
339
340
341
342
343 public Collection<E> getOutEdges(V vertex)
344 {
345 return getChildEdges(vertex);
346 }
347
348
349
350
351
352
353 @Override
354 public int getPredecessorCount(V vertex)
355 {
356 if (!containsVertex(vertex))
357 return -1;
358 return vertex.equals(root) ? 0 : 1;
359 }
360
361
362
363
364 public Collection<V> getPredecessors(V vertex)
365 {
366 if (!containsVertex(vertex))
367 return null;
368 if (vertex.equals(root))
369 return Collections.emptySet();
370 return Collections.singleton(getParent(vertex));
371 }
372
373
374
375
376 public V getSource(E directed_edge)
377 {
378 if (!containsEdge(directed_edge))
379 return null;
380 return edge_vpairs.get(directed_edge).getSecond();
381 }
382
383
384
385
386 @Override
387 public int getSuccessorCount(V vertex)
388 {
389 return getChildCount(vertex);
390 }
391
392
393
394
395 public Collection<V> getSuccessors(V vertex)
396 {
397 return getChildren(vertex);
398 }
399
400
401
402
403 @Override
404 public int inDegree(V vertex)
405 {
406 if (!containsVertex(vertex))
407 return 0;
408 if (vertex.equals(root))
409 return 0;
410 return 1;
411 }
412
413
414
415
416 public boolean isDest(V vertex, E edge)
417 {
418 if (!containsEdge(edge) || !containsVertex(vertex))
419 return false;
420 return edge_vpairs.get(edge).getSecond().equals(vertex);
421 }
422
423
424
425
426
427
428
429 public boolean isLeaf(V vertex)
430 {
431 if (!containsVertex(vertex))
432 return false;
433 return outDegree(vertex) == 0;
434 }
435
436
437
438
439
440
441
442
443 @Override
444 public boolean isPredecessor(V v1, V v2)
445 {
446 if (!containsVertex(v2))
447 return false;
448 return getParent(v2).equals(v1);
449 }
450
451
452
453
454
455
456
457 public boolean isRoot(V vertex)
458 {
459 if (root == null)
460 return false;
461 return root.equals(vertex);
462 }
463
464
465
466
467 public boolean isSource(V vertex, E edge)
468 {
469 if (!containsEdge(edge) || !containsVertex(vertex))
470 return false;
471 return edge_vpairs.get(edge).getFirst().equals(vertex);
472 }
473
474
475
476
477 @Override
478 public boolean isSuccessor(V v1, V v2)
479 {
480 if (!containsVertex(v2))
481 return false;
482 if (containsVertex(v1))
483 return getParent(v1).equals(v2);
484 return isLeaf(v2) && v1 == null;
485 }
486
487
488
489
490 @Override
491 public int outDegree(V vertex)
492 {
493 if (!containsVertex(vertex))
494 return 0;
495 List<E> out_edges = vertex_data.get(vertex).child_edges;
496 if (out_edges == null)
497 return 0;
498 int degree = 0;
499 for (E e : out_edges)
500 degree += (e == null) ? 0 : 1;
501 return degree;
502 }
503
504
505
506
507 @Override
508 @SuppressWarnings("unchecked")
509 public boolean addEdge(E edge, Collection<? extends V> vertices, EdgeType edge_type)
510 {
511 if (edge == null || vertices == null)
512 throw new IllegalArgumentException("inputs may not be null");
513 if (vertices.size() != 2)
514 throw new IllegalArgumentException("'vertices' must contain " +
515 "exactly 2 distinct vertices");
516 this.validateEdgeType(edge_type);
517 Pair<V> endpoints;
518 if (vertices instanceof Pair)
519 endpoints = (Pair<V>)vertices;
520 else
521 endpoints = new Pair<V>(vertices);
522 V v1 = endpoints.getFirst();
523 V v2 = endpoints.getSecond();
524 if (v1.equals(v2))
525 throw new IllegalArgumentException("Input vertices must be distinct");
526 return addEdge(edge, v1, v2);
527 }
528
529
530
531
532 public boolean addVertex(V vertex)
533 {
534 if(root == null)
535 {
536 this.root = vertex;
537 vertex_data.put(vertex, new VertexData(null, 0));
538 this.height = 0;
539 return true;
540 }
541 else
542 {
543 throw new UnsupportedOperationException("Unless you are setting " +
544 "the root, use addEdge() or addChild()");
545 }
546 }
547
548
549
550
551 @Override
552 public boolean isIncident(V vertex, E edge)
553 {
554 if (!containsVertex(vertex) || !containsEdge(edge))
555 return false;
556 return edge_vpairs.get(edge).contains(vertex);
557 }
558
559
560
561
562 @Override
563 public boolean isNeighbor(V v1, V v2)
564 {
565 if (!containsVertex(v1) || !containsVertex(v2))
566 return false;
567 return getNeighbors(v1).contains(v2);
568 }
569
570
571
572
573 public boolean containsEdge(E edge)
574 {
575 return edge_vpairs.containsKey(edge);
576 }
577
578
579
580
581 public boolean containsVertex(V vertex)
582 {
583 return vertex_data.containsKey(vertex);
584 }
585
586
587
588
589
590 @Override
591 public E findEdge(V v1, V v2)
592 {
593 if (!containsVertex(v1) || !containsVertex(v2))
594 return null;
595 VertexData v1_data = vertex_data.get(v1);
596 if (edge_vpairs.get(v1_data.parent_edge).getFirst().equals(v2))
597 return v1_data.parent_edge;
598 List<E> edges = v1_data.child_edges;
599 if (edges == null)
600 return null;
601 for (E edge : edges)
602 if (edge != null && edge_vpairs.get(edge).getSecond().equals(v2))
603 return edge;
604 return null;
605 }
606
607
608
609
610 @Override
611 public Collection<E> findEdgeSet(V v1, V v2)
612 {
613 E edge = findEdge(v1, v2);
614 if (edge == null)
615 return Collections.emptySet();
616 else
617 return Collections.singleton(edge);
618 }
619
620
621
622
623
624
625
626
627
628
629
630 public V getChild(V vertex, int index)
631 {
632 if (index < 0 || index >= order)
633 throw new ArrayIndexOutOfBoundsException(index + " is not in [0, order-1]");
634 if (!containsVertex(vertex))
635 return null;
636 List<E> edges = vertex_data.get(vertex).child_edges;
637 if (edges == null)
638 return null;
639 E edge = edges.get(index);
640 return edge == null ? null : edge_vpairs.get(edge).getSecond();
641 }
642
643
644
645
646 public int getEdgeCount()
647 {
648 return edge_vpairs.size();
649 }
650
651
652
653
654 public Collection<E> getEdges()
655 {
656 return new ImmutableSet.Builder<E>().addAll(edge_vpairs.keySet()).build();
657
658 }
659
660
661
662
663 @Override
664 public int getIncidentCount(E edge)
665 {
666 return 2;
667 }
668
669
670
671
672 public Collection<E> getIncidentEdges(V vertex)
673 {
674 if (!containsVertex(vertex))
675 return null;
676 ArrayList<E> edges = new ArrayList<E>(order+1);
677 VertexData v_data = vertex_data.get(vertex);
678 if (v_data.parent_edge != null)
679 edges.add(v_data.parent_edge);
680 if (v_data.child_edges != null)
681 {
682 for (E edge : v_data.child_edges)
683 if (edge != null)
684 edges.add(edge);
685 }
686 if (edges.isEmpty())
687 return Collections.emptySet();
688 return Collections.unmodifiableCollection(edges);
689 }
690
691
692
693
694 @Override
695 public Collection<V> getIncidentVertices(E edge)
696 {
697 return edge_vpairs.get(edge);
698 }
699
700
701
702
703 @Override
704 public int getNeighborCount(V vertex)
705 {
706 if (!containsVertex(vertex))
707 return 0;
708 return (vertex.equals(root) ? 0 : 1) + this.getChildCount(vertex);
709 }
710
711
712
713
714 public Collection<V> getNeighbors(V vertex)
715 {
716 if (!containsVertex(vertex))
717 return null;
718 ArrayList<V> vertices = new ArrayList<V>(order+1);
719 VertexData v_data = vertex_data.get(vertex);
720 if (v_data.parent_edge != null)
721 vertices.add(edge_vpairs.get(v_data.parent_edge).getFirst());
722 if (v_data.child_edges != null)
723 {
724 for (E edge : v_data.child_edges)
725 if (edge != null)
726 vertices.add(edge_vpairs.get(edge).getSecond());
727 }
728 if (vertices.isEmpty())
729 return Collections.emptySet();
730 return Collections.unmodifiableCollection(vertices);
731 }
732
733
734
735
736 public int getVertexCount()
737 {
738 return vertex_data.size();
739 }
740
741
742
743
744 public Collection<V> getVertices()
745 {
746 return new ImmutableSet.Builder<V>().addAll(vertex_data.keySet()).build();
747
748 }
749
750
751
752
753 public boolean removeEdge(E edge)
754 {
755 if (!containsEdge(edge))
756 return false;
757
758 removeVertex(edge_vpairs.get(edge).getSecond());
759 edge_vpairs.remove(edge);
760
761 return true;
762 }
763
764
765
766
767 public boolean removeVertex(V vertex)
768 {
769 if (!containsVertex(vertex))
770 return false;
771
772
773 for(V v : getChildren(vertex))
774 removeVertex(v);
775
776 E parent_edge = getParentEdge(vertex);
777 edge_vpairs.remove(parent_edge);
778 List<E> edges = vertex_data.get(vertex).child_edges;
779 if (edges != null)
780 for (E edge : edges)
781 edge_vpairs.remove(edge);
782 vertex_data.remove(vertex);
783
784 return true;
785 }
786
787 protected class VertexData
788 {
789 List<E> child_edges;
790 E parent_edge;
791 int depth;
792
793 protected VertexData(E parent_edge, int depth)
794 {
795 this.parent_edge = parent_edge;
796 this.depth = depth;
797 }
798 }
799
800 @Override
801 public boolean addEdge(E edge, Pair<? extends V> endpoints, EdgeType edgeType)
802 {
803 if (edge == null || endpoints == null)
804 throw new IllegalArgumentException("inputs must not be null");
805 return addEdge(edge, endpoints.getFirst(), endpoints.getSecond(), edgeType);
806 }
807 }