这两天趁复习算法之际,顺便实现了下插入、合并、堆和快速排序。不解释,贴点代码算是给自己留下备日后复习。
/** * Sort the array of a * Just like a number of n cards on the desk, you pick one by one, each time you pick up one card, insert into the correct place into the cards in your hand * @param <T> * @param a */ @SuppressWarnings("unchecked") public static <T extends Comparable<?>> T[] insertSort(T[] a){ if( a == null || a.length == 0 ) return null; for( int i = 1; i < a.length; ++i){ T key = a[i]; int j = i - 1; while( j >= 0 && ((Comparable)a[j]).compareTo(key) > 0 ){ //if a[j] > key a[j+1] = a[j]; j--; } a[j+1] = key; } return a; }
public static <T extends Comparable<?>> void mergeSort(T[] a, int low, int high){ if( low < high){ int q = (low + high) / 2;//(0+3)/2 = 1 a,0,1 ==> q = 0 a 00,11 a,2,3 mergeSort(a,low,q); mergeSort(a,q+1,high); merge(a,low,q,high); } } /** * Merge two sorted sub arrays into a whole array * Suppose the sub arrays a[p,p+1,...q] and a[q+1,q+2,...r] are the sorted arrays * Merge these two sub arrays into the whole array T[] a to make it sorted array */ @SuppressWarnings("unchecked") public static <T extends Comparable<?>>void merge(T[] a, int p, int q, int r){ int n1 = q - p + 1; int n2 = r - q; T[] L = (T[]) Array.newInstance(Comparable.class, n1); for( int i = 0; i < n1; i++) L[i] = a[p+i]; T[] R = (T[]) Array.newInstance(Comparable.class, n2); for( int i = 0; i < n2; i++) R[i] = a[q+1+i]; int i = 0, j = 0, k = p; while( k < r && i < n1 && j < n2){ if( ((Comparable)L[i]).compareTo(R[j]) < 0 ){ //L[i] < R[j] a[k] = L[i]; i++; }else{ a[k] = R[j]; j++; } k++; } if( i >= n1){ while( j < n2){ a[k] = R[j]; k++; j++; } } if( j >= n2 ){ while( i < n1 ){ a[k] = L[i]; k++; i++; } } }
public static <T extends Comparable<?>> void heapSort(T[] a){
buildMaxHeap(a); for( int i = 1; i < a.length; ++i){ swap(a,1,a.length - i);//注意这里是1 不是i maxHeapify(a, 1, a.length - i - 1 );//是1 } } public static <T extends Comparable<?>> void swap(T[] a, int i, int j){ T temp = a[i]; a[i] = a[j]; a[j] = temp; } /** * 给定一个数组,构建一个大顶堆 * 对于满二叉树,子数组a[length/2 + 1],....a[length] 为叶子节点, * 所以只要从a[length/2]开始直至a[1],一次进行对调整即可 * @param <T> * @param a */ public static <T extends Comparable<?>> void buildMaxHeap(T[] a){ for( int i = (a.length-1)/2; i > 0; i--){ maxHeapify(a,i, a.length - 1); } } /** * 保持大顶堆操作 * 假设a中第i个元素为根的子树不符合打顶堆性质 * 思想:比较i和两个子女,若子女中最大者比i大,则交换之,继续以交换的子女为根调整 * @param <T> * @param a * @param i */ @SuppressWarnings("unchecked") public static <T extends Comparable<?>> void maxHeapify(T[] a, int i, int heapSize){ int largest = -1; int left = i<<1; int right = left+1; if( left <= heapSize && ((Comparable)a[left]).compareTo(a[i]) > 0){ largest = left; }else{ largest = i; } if( right <= heapSize && ((Comparable)a[right]).compareTo(a[largest]) > 0){ largest = right; } if( largest != i ){ T tmp = a[i]; a[i] = a[largest]; a[largest] = tmp; maxHeapify(a, largest, heapSize); } }
public static <T extends Comparable<?>> void quickSort(T[] a, int p, int r){
if( p < r ){ int q = partition(a, p, r); quickSort(a,p,q-1); quickSort(a,q+1,r); } } @SuppressWarnings("unchecked") public static <T extends Comparable<?>> int partition(T[] a, int p, int r){ T x = a[r]; /** * i 用来指明当前比a[r]小得区域,初始状态该区域为空,所以置初始值 i = p - 1 * j 用来指示当前扫描到的元素,从p开始扫描,初始值 j = p * 当发现a[j]比a[r]小或等,则把a[j]放到i指示的区域:很简单,先i自增即找到大于a[r]的区域中第一个元素,然后交换a[i]和a[p],做完以后,i的区域增加了一个小于a[r]的元素 * 最后,a[i+1]即位x的位置 */ int i = p - 1; for(int j = p; j < r; ++j){ if(((Comparable)a[j]).compareTo(x) <= 0){ HeapSortor.swap(a, ++i, j); } } HeapSortor.swap(a,i+1,r); return i+1; }