1. Merge Sort / 归并排序
/* Divide and conquer * 将一个数组中的两个相邻有序区间合并成一个 * * 参数说明: * A -- 包含两个有序区间的数组 * lo -- 第1个有序区间的起始地址。 * mi -- 第1个有序区间的结束地址。也是第2个有序区间的起始地址。 * hi -- 第2个有序区间的结束地址。 */
1 void merge(int A[],int lo,int hi,int mi){ 2 //以mi为界、各自有序癿子向量[lo, mi)和[mi, hi) 3 int temp[hi-lo+1]; 4 int i=lo, j=mi+1, k=0; 5 6 while(i<=mid&&j<=lo){ 7 if(A[i]<=A[j]) 8 temp[k++]=A[i++]; 9 else 10 temp[k++]=A[j++]; 11 } 12 while(i<=mid) temp[k++]=A[i++]; 13 while(j<=hi) temp[k++]=A[j++]; 14 15 for(i=0;i<k;i++) 16 A[lo++]=temp[i++]; 17 } 18 19 void mergeSort(int lo,int hi){ 20 if(hi-lo < 2) return; 21 22 int mi=(hi+lo)>>1; 23 mergeSort(lo,mi); 24 mergeSort(mi,hi); 25 merge(lo,hi,mi); 26 }
2. Quick Sort /快排
/* Divide and conquer * * - 在R[low,high]中任选一个记录作为基准(Pivot), * 以此基准将当前无序区划分为左、右两个较小的子区间R[low,pivotpos-1)和R[pivotpos+1,high], * * - 并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,此时左标记向右移动, * 直到左标记的关键字大于右标记的关键字,这时左标记停下,右标记同理进行操作。 * 直到左标记和右标记都停下时,分两种情况讨论: * 1.左标记与右标记不在同一位置,此时交换左右两标记的关键字 * 2.左右标记在同一位置,此时交换这一位置关键字和基准的位置 * * - 此后就是分两边情况递归 */
1 void QuickSort(int R[],int low,int high){ 2 int i,j,temp; 3 i=low; j=high; 4 if(low<high){ 5 temp=R[low]; 6 while(i!=j){ 7 while(i<j&&R[j]>=temp) 8 j--; 9 if(i<j) 10 R[i++]=R[j]; 11 12 while(i<j&&R[i]<temp) 13 i++; 14 if(i<j) 15 R[j--]=R[i]; 16 } 17 R[i]=temp; 18 QuickSort(R,low,i-1); 19 QuickSort(R,i+1,high); 20 } 21 }
3. 冒泡排序
/*
* 借助布尔型标志位sorted,可及时提前退出,而不致蛮力地做n-1趟扫描交换 * 对尾部有序(或接近有序)的输入,算法依然亦步亦趋地收敛,导致元素比较次数过多
*/
void bubblesort1 ( int A[], int n ) { for ( bool sorted = false; sorted = !sorted; n-- ) {
//在尚未确认已全局排序之前,逐趟进行扫描交换 for ( int i = 1; i < n; i++ ) {
//自左向右逐对检查当前范围A[0, n)内的各相邻元素 if ( A[i-1] > A[i] ){ swap ( A[i-1], A[i] ); sorted = false; //因整体排序不能保证,需要清除排序标志 } } } }
void bubblesort2 ( int A[], int n ) { for ( bool sorted = false; sorted = !sorted; n-- ) { //在尚未确认已全局排序之前,逐趟进行扫描交换 for ( int i = 1; i < n; i++ ) { //自左向右逐对检查当前范围A[0, n)内的各相邻元素 if ( A[i-1] > A[i] ) { //一旦A[i-1]与A[i]逆序,则 swap ( A[i-1], A[i] ); //交换之,并 sorted = false; //因整体排序不能保证,需要清除排序标志 } } } }
/* * 借助整数m尽快地收缩待排序区间:既可提前退出,更可减少每趟(及所有)扫描交换中元素比较操作 * 对尾部有序(或接近有序)的输入,算法收敛的速度大大提高 * 元素交换的次数仅取决于输入序列,与版本1和版本2相同 */
1 void bubblesort3 ( int A[], int n ) { 2 for ( int m; 1 < n; n = m ) { //在尚未确认已全局排序之前,逐趟进行扫描交换 3 for ( int i = m = 1; i < n; i++ ) { //自左向右逐对检查当前范围A[0, m)内的各相邻元素 4 if ( A[i-1] > A[i] ) { //一旦A[i-1]与A[i]逆序,则 5 swap ( A[i-1], A[i] ); //交换之,并 6 m = i; //更新待排序区间的长度 7 } 8 } 9 } 10 }