Improvements:
1. If the number of elements is less than 10, use insertion sort.
2. If the number of elements is more, swap the first element with mid element.
3. If the number of elements is even more, swap the first element of the subarray with the median of the three elements (lo, mid, hi).
4. If the number of elements is even more, swap the first element with (Tukey's Ninther).
Source:
package ThreeWayQuickSort; import java.util.Arrays; public class ThreeWayQuicksort { public static void qSort(int[] a){ qSorter(a, 0, a.length-1); } private static void qSorter(int[] a, int lo, int hi){ if(lo>=hi) return; /* If the sub array is of size 10 or less it is better to use insertion sort instead */ if (hi - lo <= 10) { InsertionSort.insertionSort(a, lo, hi); return; } if(hi - lo <= 25) { /* If the sub array is small, we can just use the middle element as the element to compare with */ swap(a, lo, (lo+hi)/2); }else if(hi - lo <= 50){ /* If the sub array is medium in size, we can use the median of three elements lo, (mid), and hi and set it as the element to compare with. */ int m = median(a, lo, (lo + hi) / 2, hi); swap(a, m, lo); }else{ //Tukey's ninther int a1[] = new int[3]; int a2[] = new int[3]; int a3[] = new int[3]; int gap = (hi-lo+1)/9; if(((hi-lo+1)+gap)%9<gap)gap++; //Tricky logic! //System.out.println("Gap = "+gap); //Indexes int a1I = 0, a2I = 0, a3I = 0, arrayNo = 0; for(int i=lo;arrayNo<9;i+=gap){ if(arrayNo < 3) a1[a1I++] = i; else if(arrayNo < 6) a2[a2I++] = i; else a3[a3I++] = i; arrayNo++; } /* Debug code System.out.println("Median of "+Arrays.toString(a1)); System.out.println("Median of "+Arrays.toString(a2)); System.out.println("Median of "+Arrays.toString(a3)); */ int median = median(a, median(a, a1[0], a1[1], a1[2]), median(a, a2[0], a2[1], a2[2]), median(a, a3[0], a3[1], a3[2])); swap(a, median, lo); //System.out.println("Ninther = "+a[lo]); } int lt = lo, gt = hi, i = lo; int v = a[lo]; while(i<=gt){ if(a[i]<v){ swap(a, i++, lt++);} else if(a[i]>v){swap(a, i, gt--);} else i++; //System.out.println(Arrays.toString(a)); } qSorter(a, lo, lt-1); qSorter(a, gt+1, hi); } public static int median(int[] x, int a, int b, int c) { if (x[a] > x[b] && x[a] > x[c]) { if (x[b] > x[c]) return b; else return c; } else if (x[b] > x[a] && x[b] > x[c]) { if (x[a] > x[c]) return a; else return c; } else if (x[c] > x[a] && x[c] > x[b]) { if (x[a] > x[b]) return a; } return b; } private static void swap(int[] array, int a, int b){ int temp = array[a]; array[a] = array[b]; array[b] = temp; } public static void main(String[] args){ //Two arrays to test //int array[] = {2,3,5,7,8,3,5,6,8,4,3,2,5,6,7,8}; int array[] = {2,3,4,1,5,6,7,8,9,10,11,2,3,4,5,2,3,14,19,20,23,22,1,4,3,2,5}; qSort(array); System.out.println(Arrays.toString(array)); } } class InsertionSort { public static void insertionSort(int[] a, int lo, int hi) { for (int i = lo + 1; i <= hi; ++i) { int j = i; while (a[j] < a[j - 1]) { int temp = a[j]; a[j] = a[j - 1]; a[j - 1] = temp; if (--j == 0) { break; } } } } }
Output for test input data:
[1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 7, 8, 9, 10, 11, 14, 19, 20, 22, 23]
No comments:
Post a Comment