1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.server.core.avltree;
21
22
23 import java.util.ArrayList;
24 import java.util.Comparator;
25 import java.util.List;
26
27
28
29
30
31
32
33
34
35 public class AvlTreeMapImpl<K, V> implements AvlTreeMap<K, V>
36 {
37
38 private LinkedAvlMapNode<K, V> root;
39
40
41 private Comparator<K> keyComparator;
42
43
44 private Comparator<V> valueComparator;
45
46
47 private LinkedAvlMapNode<K, V> first;
48
49
50 private LinkedAvlMapNode<K, V> last;
51
52
53 private boolean allowDuplicates;
54
55
56 private int size;
57
58
59
60
61
62
63
64
65 public AvlTreeMapImpl( Comparator<K> keyComparator, Comparator<V> valueComparator )
66 {
67 this( keyComparator, valueComparator, false );
68 }
69
70
71
72
73
74
75
76
77
78 public AvlTreeMapImpl( Comparator<K> keyComparator, Comparator<V> valueComparator, boolean allowDuplicates )
79 {
80 this.keyComparator = keyComparator;
81 this.valueComparator = valueComparator;
82 this.allowDuplicates = allowDuplicates;
83 }
84
85
86
87
88
89 public Comparator<K> getKeyComparator()
90 {
91 return keyComparator;
92 }
93
94
95
96
97
98 public Comparator<V> getValueComparator()
99 {
100 return valueComparator;
101 }
102
103
104 private void dump( LinkedAvlMapNode<K, V> node )
105 {
106 if ( node.left != null )
107 {
108 dump( node.left );
109 }
110
111 if ( node.value.isSingleton() )
112 {
113 System.out.print( "<" + node.key + "," + node.value.getSingleton() + ">" );
114 }
115 else
116 {
117 AvlTree<V> values = node.value.getOrderedSet();
118 System.out.print( "<" + node.key + "," );
119 boolean isFirst = true;
120
121 for ( V value : values.getKeys() )
122 {
123 if ( isFirst )
124 {
125 isFirst = false;
126 }
127 else
128 {
129 System.out.print( "," );
130 }
131
132 System.out.print( value );
133 }
134
135 System.out.print( ">" );
136
137 }
138
139 if ( node.right != null )
140 {
141 dump( node.right );
142 }
143 }
144
145
146
147
148 public V insert( K key, V value )
149 {
150 LinkedAvlMapNode<K, V> node, temp;
151 LinkedAvlMapNode<K, V> parent = null;
152 int c;
153
154 if ( root == null )
155 {
156 root = new LinkedAvlMapNode<>( key, value );
157 first = root;
158 last = root;
159 size++;
160 return null;
161 }
162
163 node = new LinkedAvlMapNode<>( key, value );
164
165 temp = root;
166
167 List<LinkedAvlMapNode<K, V>> treePath = new ArrayList<>();
168
169 while ( temp != null )
170 {
171 treePath.add( 0, temp );
172 parent = temp;
173
174 c = keyComparator.compare( key, temp.getKey() );
175
176 if ( c == 0 )
177 {
178 V returnValue;
179
180 if ( allowDuplicates )
181 {
182 returnValue = insertDupKey( value, temp );
183 }
184 else
185 {
186
187 returnValue = temp.value.setSingleton( value );
188 }
189
190 return returnValue;
191 }
192
193 if ( c < 0 )
194 {
195 temp.isLeft = true;
196 temp = temp.getLeft();
197 }
198 else
199 {
200 temp.isLeft = false;
201 temp = temp.getRight();
202 }
203 }
204
205 c = keyComparator.compare( key, parent.getKey() );
206
207 if ( c < 0 )
208 {
209 parent.setLeft( node );
210 }
211 else
212 {
213 parent.setRight( node );
214 }
215
216 insertInList( node, parent, c );
217
218 treePath.add( 0, node );
219 balance( treePath );
220
221 size++;
222
223 return null;
224 }
225
226
227 private V insertDupKey( V value, LinkedAvlMapNode<K, V> existingNode )
228 {
229 AvlTree<V> dupsTree = null;
230
231 if ( existingNode.value.isOrderedSet() )
232 {
233 dupsTree = existingNode.value.getOrderedSet();
234 }
235 else
236 {
237
238 dupsTree = new AvlTreeImpl<>( valueComparator );
239 dupsTree.insert( existingNode.value.getSingleton() );
240 existingNode.value.switchToOrderedSet( dupsTree );
241 }
242
243
244 if ( dupsTree.find( value ) != null )
245 {
246 return value;
247 }
248
249
250 dupsTree.insert( value );
251
252 return null;
253 }
254
255
256 private void removeFromList( LinkedAvlMapNode<K, V> node )
257 {
258 if ( node.next == null && node.previous == null )
259 {
260 first = null;
261 last = null;
262 }
263 else if ( node.next == null )
264 {
265 node.previous.next = null;
266 last = node.previous;
267 }
268 else if ( node.previous == null )
269 {
270 node.next.previous = null;
271 first = node.next;
272 }
273 else
274
275 {
276 node.previous.next = node.next;
277 node.next.previous = node.previous;
278 }
279
280 }
281
282
283 private void insertInList( LinkedAvlMapNode<K, V> node, LinkedAvlMapNode<K, V> parentNode, int pos )
284 {
285
286 if ( pos < 0 )
287 {
288 if ( last == null )
289 {
290 last = parentNode;
291 }
292
293 if ( parentNode.previous == null )
294 {
295 first = node;
296 }
297 else
298 {
299 parentNode.previous.next = node;
300 node.previous = parentNode.previous;
301 }
302
303 node.next = parentNode;
304 parentNode.previous = node;
305 }
306 else if ( pos > 0 )
307 {
308 if ( parentNode.next == null )
309 {
310 last = node;
311 }
312 else
313 {
314 parentNode.next.previous = node;
315 node.next = parentNode.next;
316 }
317 node.previous = parentNode;
318 parentNode.next = node;
319 }
320
321 }
322
323
324
325
326
327 public SingletonOrOrderedSet<V> remove( K key )
328 {
329 if ( key == null )
330 {
331 throw new IllegalArgumentException( "key cannot be null" );
332 }
333
334 LinkedAvlMapNode<K, V> temp = null;
335
336 List<LinkedAvlMapNode<K, V>> treePath = new ArrayList<>();
337
338 treePath = find( key, root, treePath );
339
340 if ( treePath == null )
341 {
342 return null;
343 }
344
345 temp = treePath.remove( 0 );
346
347 if ( temp.isLeaf() && ( temp == root ) )
348 {
349 root = null;
350 }
351 else
352 {
353 balanceNodesAfterRemove( treePath, temp );
354 }
355
356 size--;
357 return temp.value;
358 }
359
360
361
362
363
364 public V remove( K key, V value )
365 {
366 if ( key == null || value == null )
367 {
368 throw new IllegalArgumentException( "key or value cannot be null" );
369 }
370
371 LinkedAvlMapNode<K, V> temp = null;
372
373 List<LinkedAvlMapNode<K, V>> treePath = new ArrayList<>();
374
375 treePath = find( key, root, treePath );
376
377 if ( treePath == null )
378 {
379 return null;
380 }
381
382 temp = treePath.remove( 0 );
383
384
385 if ( allowDuplicates )
386 {
387 if ( temp.value.isOrderedSet() )
388 {
389 AvlTree<V> dupsTree = temp.value.getOrderedSet();
390 V removedVal = dupsTree.remove( value );
391
392
393
394
395
396
397
398 if ( ( removedVal == null ) || !dupsTree.isEmpty() )
399 {
400 return removedVal;
401 }
402 }
403 else
404 {
405 if ( valueComparator.compare( temp.value.getSingleton(), value ) != 0 )
406 {
407 return null;
408 }
409 }
410 }
411
412 if ( temp.isLeaf() && ( temp == root ) )
413 {
414 if ( allowDuplicates )
415 {
416 if ( temp.value.isSingleton() || temp.value.getOrderedSet().isEmpty() )
417 {
418 root = null;
419 }
420 }
421 else
422
423 {
424 root = null;
425 }
426
427 size--;
428 return value;
429 }
430
431 balanceNodesAfterRemove( treePath, temp );
432
433 size--;
434 return value;
435 }
436
437
438
439
440
441
442
443
444
445 private void balanceNodesAfterRemove( List<LinkedAvlMapNode<K, V>> treePath, LinkedAvlMapNode<K, V> delNode )
446 {
447 LinkedAvlMapNode<K, V> y = null;
448
449
450 removeFromList( delNode );
451
452 if ( delNode.isLeaf() )
453 {
454 if ( !treePath.isEmpty() )
455 {
456 detachNodes( delNode, treePath.get( 0 ) );
457 }
458 }
459 else
460 {
461 if ( delNode.left != null )
462 {
463 List<LinkedAvlMapNode<K, V>> leftTreePath = findMax( delNode.left );
464 y = leftTreePath.remove( 0 );
465
466 if ( leftTreePath.isEmpty() )
467 {
468 detachNodes( y, delNode );
469 }
470 else
471 {
472 detachNodes( y, leftTreePath.remove( 0 ) );
473 }
474
475 leftTreePath.addAll( treePath );
476 treePath = leftTreePath;
477
478 y.right = delNode.right;
479
480 if ( delNode == root )
481 {
482 y.left = delNode.left;
483 root = y;
484 }
485 else
486 {
487 replaceNode( delNode, y, treePath.get( 0 ) );
488 }
489 }
490 else if ( delNode.right != null )
491 {
492 List<LinkedAvlMapNode<K, V>> rightTreePath = findMin( delNode.right );
493 y = rightTreePath.remove( 0 );
494
495 if ( rightTreePath.isEmpty() )
496 {
497 detachNodes( y, delNode );
498 }
499 else
500 {
501 detachNodes( y, rightTreePath.remove( 0 ) );
502 }
503
504 rightTreePath.addAll( treePath );
505 treePath = rightTreePath;
506
507 y.right = delNode.right;
508
509 if ( delNode == root )
510 {
511 y.right = delNode.right;
512 root = y;
513 }
514 else
515 {
516 replaceNode( delNode, y, treePath.get( 0 ) );
517 }
518 }
519 }
520
521 treePath.add( 0, y );
522 balance( treePath );
523 }
524
525
526
527
528
529
530
531
532
533
534
535
536
537 private void balance( List<LinkedAvlMapNode<K, V>> treePath )
538 {
539 LinkedAvlMapNode<K, V> parentNode = null;
540
541 int treePathSize = treePath.size();
542
543 for ( LinkedAvlMapNode<K, V> node : treePath )
544 {
545 int balFactor = getBalance( node );
546
547 if ( node != root && treePath.indexOf( node ) < ( treePathSize - 1 ) )
548 {
549 parentNode = treePath.get( treePath.indexOf( node ) + 1 );
550 }
551
552 if ( balFactor > 1 )
553 {
554 if ( getBalance( node.right ) <= -1 )
555 {
556
557 rotateSingleRight( node.right, node );
558 rotateSingleLeft( node, parentNode );
559 }
560 else
561
562 {
563 rotateSingleLeft( node, parentNode );
564 }
565 }
566 else if ( balFactor < -1 )
567 {
568 if ( getBalance( node.left ) >= 1 )
569 {
570
571 rotateSingleLeft( node.left, node );
572 rotateSingleRight( node, parentNode );
573 }
574 else
575 {
576 rotateSingleRight( node, parentNode );
577 }
578 }
579 }
580 }
581
582
583
584
585
586 public boolean isEmpty()
587 {
588 return root == null;
589 }
590
591
592
593
594
595
596 public int getSize()
597 {
598 return size;
599 }
600
601
602
603
604
605
606
607
608
609 void setRoot( LinkedAvlMapNode<K, V> root )
610 {
611 this.root = root;
612 }
613
614
615
616
617
618
619
620
621
622 void setFirst( LinkedAvlMapNode<K, V> first )
623 {
624 this.first = first;
625 }
626
627
628
629
630
631
632
633
634
635 void setLast( LinkedAvlMapNode<K, V> last )
636 {
637 this.last = last;
638 }
639
640
641
642
643
644 public LinkedAvlMapNode<K, V> getRoot()
645 {
646 return root;
647 }
648
649
650
651
652
653 public List<K> getKeys()
654 {
655 List<K> keys = new ArrayList<>();
656 LinkedAvlMapNode<K, V> node = first;
657
658 while ( node != null )
659 {
660 keys.add( node.key );
661 node = node.next;
662 }
663
664 return keys;
665 }
666
667
668
669
670
671 public void printTree()
672 {
673 if ( isEmpty() )
674 {
675 System.out.println( "Tree is empty" );
676 return;
677 }
678
679 getRoot().setDepth( 0 );
680
681 System.out.println( getRoot() );
682
683 visit( getRoot().getRight(), getRoot() );
684
685 visit( getRoot().getLeft(), getRoot() );
686 }
687
688
689
690
691
692 public LinkedAvlMapNode<K, V> getFirst()
693 {
694 return first;
695 }
696
697
698
699
700
701 public LinkedAvlMapNode<K, V> getLast()
702 {
703 return last;
704 }
705
706
707
708
709
710
711
712
713 private void rotateSingleLeft( LinkedAvlMapNode<K, V> node, LinkedAvlMapNode<K, V> parentNode )
714 {
715 LinkedAvlMapNode<K, V> temp;
716
717
718 temp = node.right;
719 node.right = temp.left;
720 temp.left = node;
721
722 if ( node == root )
723 {
724 root = temp;
725 }
726 else if ( parentNode != null )
727 {
728 if ( parentNode.left == node )
729 {
730 parentNode.left = temp;
731 }
732 else if ( parentNode.right == node )
733 {
734 parentNode.right = temp;
735 }
736 }
737 }
738
739
740
741
742
743
744
745
746 private void rotateSingleRight( LinkedAvlMapNode<K, V> node, LinkedAvlMapNode<K, V> parentNode )
747 {
748 LinkedAvlMapNode<K, V> temp;
749
750
751 temp = node.left;
752 node.left = temp.right;
753 temp.right = node;
754
755 if ( node == root )
756 {
757 root = temp;
758 }
759 else if ( parentNode != null )
760 {
761 if ( parentNode.left == node )
762 {
763 parentNode.left = temp;
764 }
765 else if ( parentNode.right == node )
766 {
767 parentNode.right = temp;
768 }
769 }
770
771
772
773
774 else if ( root != null && root.left == node )
775 {
776 root.left = temp;
777
778 }
779 }
780
781
782
783
784
785
786
787
788 private void detachNodes( LinkedAvlMapNode<K, V> node, LinkedAvlMapNode<K, V> parentNode )
789 {
790 if ( parentNode != null )
791 {
792 if ( node == parentNode.left )
793 {
794 parentNode.left = node.left;
795 }
796 else if ( node == parentNode.right )
797 {
798 parentNode.right = node.left;
799 }
800 }
801 }
802
803
804
805
806
807
808
809
810
811
812 private void replaceNode( LinkedAvlMapNode<K, V> deleteNode, LinkedAvlMapNode<K, V> replaceNode,
813 LinkedAvlMapNode<K, V> parentNode )
814 {
815 if ( parentNode != null )
816 {
817 replaceNode.left = deleteNode.left;
818
819 if ( deleteNode == parentNode.left )
820 {
821 parentNode.left = replaceNode;
822 }
823 else if ( deleteNode == parentNode.right )
824 {
825 parentNode.right = replaceNode;
826 }
827 }
828 }
829
830
831
832
833
834
835
836
837
838
839
840 private List<LinkedAvlMapNode<K, V>> find( K key, LinkedAvlMapNode<K, V> startNode,
841 List<LinkedAvlMapNode<K, V>> path )
842 {
843 int c;
844
845 if ( startNode == null )
846 {
847 return null;
848 }
849
850 path.add( 0, startNode );
851 c = keyComparator.compare( key, startNode.key );
852
853 if ( c == 0 )
854 {
855 return path;
856 }
857 else if ( c > 0 )
858 {
859 return find( key, startNode.right, path );
860 }
861 else
862 {
863 return find( key, startNode.left, path );
864 }
865 }
866
867
868
869
870
871 public LinkedAvlMapNode<K, V> findGreater( K key )
872 {
873 LinkedAvlMapNode<K, V> result = fetchNonNullNode( key, root, root );
874
875 if ( result == null )
876 {
877 return null;
878 }
879 else if ( keyComparator.compare( key, result.key ) < 0 )
880 {
881 return result;
882 }
883
884 return result.next;
885 }
886
887
888
889
890
891 public LinkedAvlMapNode<K, V> findGreaterOrEqual( K key )
892 {
893 LinkedAvlMapNode<K, V> result = fetchNonNullNode( key, root, root );
894
895 if ( result == null )
896 {
897 return null;
898 }
899 else if ( keyComparator.compare( key, result.key ) <= 0 )
900 {
901 return result;
902 }
903
904 return result.next;
905 }
906
907
908
909
910
911 public LinkedAvlMapNode<K, V> findLess( K key )
912 {
913 LinkedAvlMapNode<K, V> result = fetchNonNullNode( key, root, root );
914
915 if ( result == null )
916 {
917 return null;
918 }
919 else if ( keyComparator.compare( key, result.key ) > 0 )
920 {
921 return result;
922 }
923
924 return result.previous;
925 }
926
927
928
929
930
931 public LinkedAvlMapNode<K, V> findLessOrEqual( K key )
932 {
933 LinkedAvlMapNode<K, V> result = fetchNonNullNode( key, root, root );
934
935 if ( result == null )
936 {
937 return null;
938 }
939 else if ( keyComparator.compare( key, result.key ) >= 0 )
940 {
941 return result;
942 }
943
944 return result.previous;
945 }
946
947
948
949
950
951
952
953 private LinkedAvlMapNode<K, V> fetchNonNullNode( K key, LinkedAvlMapNode<K, V> startNode,
954 LinkedAvlMapNode<K, V> parent )
955 {
956
957 if ( startNode == null )
958 {
959 return parent;
960 }
961
962 int c = keyComparator.compare( key, startNode.key );
963
964 parent = startNode;
965
966 if ( c > 0 )
967 {
968 return fetchNonNullNode( key, startNode.right, parent );
969 }
970 else if ( c < 0 )
971 {
972 return fetchNonNullNode( key, startNode.left, parent );
973 }
974
975 return startNode;
976 }
977
978
979
980
981
982 public LinkedAvlMapNode<K, V> find( K key )
983 {
984 return find( key, root );
985 }
986
987
988
989
990
991 public LinkedAvlMapNode<K, V> find( K key, V value )
992 {
993 if ( key == null || value == null )
994 {
995 return null;
996 }
997
998 LinkedAvlMapNode<K, V> node = find( key, root );
999
1000 if ( node == null )
1001 {
1002 return null;
1003 }
1004
1005 if ( node.value.isOrderedSet() )
1006 {
1007 AvlTree<V> dupsTree = node.value.getOrderedSet();
1008
1009 if ( dupsTree.find( value ) == null )
1010 {
1011 return null;
1012 }
1013 }
1014 else
1015 {
1016 if ( valueComparator.compare( node.value.getSingleton(), value ) != 0 )
1017 {
1018 return null;
1019 }
1020 }
1021
1022 return node;
1023 }
1024
1025
1026 private LinkedAvlMapNode<K, V> find( K key, LinkedAvlMapNode<K, V> startNode )
1027 {
1028 int c;
1029
1030 if ( startNode == null )
1031 {
1032 return null;
1033 }
1034
1035 c = keyComparator.compare( key, startNode.key );
1036
1037 if ( c > 0 )
1038 {
1039 startNode.isLeft = false;
1040 return find( key, startNode.right );
1041 }
1042 else if ( c < 0 )
1043 {
1044 startNode.isLeft = true;
1045 return find( key, startNode.left );
1046 }
1047
1048 return startNode;
1049 }
1050
1051
1052
1053
1054
1055
1056
1057
1058 private List<LinkedAvlMapNode<K, V>> findMax( LinkedAvlMapNode<K, V> startNode )
1059 {
1060 LinkedAvlMapNode<K, V> x = startNode;
1061 LinkedAvlMapNode<K, V> y = null;
1062 List<LinkedAvlMapNode<K, V>> path;
1063
1064 if ( x == null )
1065 {
1066 return null;
1067 }
1068
1069 while ( x.right != null )
1070 {
1071 x.isLeft = false;
1072 y = x;
1073 x = x.right;
1074 }
1075
1076 path = new ArrayList<>( 2 );
1077 path.add( x );
1078
1079 if ( y != null )
1080 {
1081 path.add( y );
1082 }
1083
1084 return path;
1085 }
1086
1087
1088
1089
1090
1091
1092
1093
1094 private List<LinkedAvlMapNode<K, V>> findMin( LinkedAvlMapNode<K, V> startNode )
1095 {
1096 LinkedAvlMapNode<K, V> x = startNode;
1097 LinkedAvlMapNode<K, V> y = null;
1098 List<LinkedAvlMapNode<K, V>> path;
1099
1100 if ( x == null )
1101 {
1102 return null;
1103 }
1104
1105 while ( x.left != null )
1106 {
1107 x.isLeft = true;
1108 y = x;
1109 x = x.left;
1110 }
1111
1112 path = new ArrayList<>( 2 );
1113 path.add( x );
1114
1115 if ( y != null )
1116 {
1117 path.add( y );
1118 }
1119
1120 return path;
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130 private int getBalance( LinkedAvlMapNode<K, V> node )
1131 {
1132 if ( node == null )
1133 {
1134 return 0;
1135 }
1136
1137 return node.getBalance();
1138 }
1139
1140
1141 private void visit( LinkedAvlMapNode<K, V> node, LinkedAvlMapNode<K, V> parentNode )
1142 {
1143 if ( node == null )
1144 {
1145 return;
1146 }
1147
1148 if ( !node.isLeaf() )
1149 {
1150 node.setDepth( parentNode.getDepth() + 1 );
1151 }
1152
1153 for ( int i = 0; i < parentNode.getDepth(); i++ )
1154 {
1155 System.out.print( "| " );
1156 }
1157
1158 String type = "";
1159 if ( node == parentNode.left )
1160 {
1161 type = "L";
1162 }
1163 else if ( node == parentNode.right )
1164 {
1165 type = "R";
1166 }
1167
1168 System.out.println( "|--" + node + type );
1169
1170 if ( node.getRight() != null )
1171 {
1172 visit( node.getRight(), node );
1173 }
1174
1175 if ( node.getLeft() != null )
1176 {
1177 visit( node.getLeft(), node );
1178 }
1179 }
1180
1181
1182
1183
1184
1185 public boolean isDupsAllowed()
1186 {
1187 return allowDuplicates;
1188 }
1189
1190
1191
1192
1193
1194 public void removeAll()
1195 {
1196 LinkedAvlMapNode<K, V> tmp;
1197
1198 while ( first != null )
1199 {
1200 tmp = first;
1201 first = tmp.next;
1202 tmp = null;
1203 }
1204
1205 last = null;
1206 root = null;
1207 size = 0;
1208 }
1209 }