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 }