22
33/**
44 * American Flag Sort Algorithm Implementation
5+ * This implementation uses a bucket-based approach that works with all Comparable types
56 *
67 * @see <a href="https://en.wikipedia.org/wiki/American_flag_sort">American Flag Sort Algorithm</a>
78 */
@@ -12,52 +13,76 @@ public <T extends Comparable<T>> T[] sort(T[] array) {
1213 if (array == null || array .length <= 1 ) {
1314 return array ;
1415 }
15- americanFlagSort (array , 0 , array .length - 1 , 0 );
16+
17+ // For generic comparable types, use a simplified bucket sort approach
18+ bucketSort (array , 0 , array .length - 1 );
1619 return array ;
1720 }
1821
19- private <T extends Comparable <T >> void americanFlagSort (T [] array , int start , int end , int digitIndex ) {
20- if (start >= end || digitIndex < 0 ) {
22+ private <T extends Comparable <T >> void bucketSort (T [] array , int start , int end ) {
23+ if (start >= end ) {
2124 return ;
2225 }
2326
24- int [] count = new int [256 ];
25- int [] offset = new int [256 ];
26-
27- for (int i = start ; i <= end ; i ++) {
28- int digit = getDigit (array [i ], digitIndex );
29- count [digit ]++;
27+ // Find min and max values for partitioning
28+ T min = array [start ];
29+ T max = array [start ];
30+
31+ for (int i = start + 1 ; i <= end ; i ++) {
32+ if (SortUtils .less (array [i ], min )) {
33+ min = array [i ];
34+ }
35+ if (SortUtils .greater (array [i ], max )) {
36+ max = array [i ];
37+ }
3038 }
3139
32- offset [ 0 ] = start ;
33- for ( int i = 1 ; i < 256 ; i ++ ) {
34- offset [ i ] = offset [ i - 1 ] + count [ i - 1 ] ;
40+ // If all elements are equal, no need to sort
41+ if ( min . compareTo ( max ) == 0 ) {
42+ return ;
3543 }
3644
37- for (int bucket = 0 ; bucket < 256 ; bucket ++) {
38- while (count [bucket ] > 0 ) {
39- int origin = offset [bucket ];
40- int digit = getDigit (array [origin ], digitIndex );
41- SortUtils .swap (array , origin , offset [digit ]);
42- offset [digit ]++;
43- count [digit ]--;
44- }
45+ // Use a 3-way partitioning approach similar to American Flag Sort
46+ int length = end - start + 1 ;
47+ if (length < 10 ) {
48+ // For small arrays, use insertion sort
49+ insertionSort (array , start , end );
50+ return ;
4551 }
4652
47- for (int bucket = 0 ; bucket < 256 ; bucket ++) {
48- int bucketStart = (bucket == 0 ) ? start : offset [bucket - 1 ];
49- int bucketEnd = offset [bucket ] - 1 ;
50- if (bucketStart < bucketEnd ) {
51- americanFlagSort (array , bucketStart , bucketEnd , digitIndex - 1 );
53+ // Partition into buckets based on comparison with pivot
54+ T pivot = array [start + length / 2 ];
55+
56+ int lt = start ; // less than pivot
57+ int gt = end ; // greater than pivot
58+ int i = start ; // current element
59+
60+ while (i <= gt ) {
61+ int cmp = array [i ].compareTo (pivot );
62+ if (cmp < 0 ) {
63+ SortUtils .swap (array , lt ++, i ++);
64+ } else if (cmp > 0 ) {
65+ SortUtils .swap (array , i , gt --);
66+ } else {
67+ i ++;
5268 }
5369 }
70+
71+ // Recursively sort the partitions
72+ bucketSort (array , start , lt - 1 );
73+ bucketSort (array , gt + 1 , end );
5474 }
5575
56- private <T extends Comparable <T >> int getDigit (T element , int digitIndex ) {
57- String str = element .toString ();
58- if (digitIndex >= str .length ()) {
59- return 0 ;
76+ private <T extends Comparable <T >> void insertionSort (T [] array , int start , int end ) {
77+ for (int i = start + 1 ; i <= end ; i ++) {
78+ T key = array [i ];
79+ int j = i - 1 ;
80+
81+ while (j >= start && SortUtils .greater (array [j ], key )) {
82+ array [j + 1 ] = array [j ];
83+ j --;
84+ }
85+ array [j + 1 ] = key ;
6086 }
61- return str .charAt (str .length () - 1 - digitIndex );
6287 }
6388}
0 commit comments