8.2.1歸併排序
第一種高效排序算法是歸併排序,按照分治三步法,對歸併排序算法介紹如下
劃分問題:把序列分成元素個數儘量相等的兩半
遞歸求解:把兩半元素分別排序
合併問題:把兩個有序表合併成一個
void merge_sort(int* A,int x,int y,int* T){
if(y-x>1){
int m=x+(y-x)/2; //劃分
int p=x,q=m,i=x;
merge_sort(A,x,m,T); //遞歸分解
merge_sort(A,m,y,T); //遞歸
while(p<m||q<y){
if(q>=y||(p<m&&A[p]<=A[q]))
T[i++]=A[p++];
else
T[i++]=A[q++];
}
for(i=x;i<y;i++)
A[i]=T[i]; //從輔助空間複製回數組A
}
}
逆序對問題
分析:n特別大,所以n*n枚舉會超時,因此需尋找更高效的方法。下面試試“分治三步法”
“劃分問題”過程是吧序列分成元素個數儘量相等的兩半;
“遞歸求解”是統計i和j均在左邊或者均在右邊的逆序數對個數;
“合併問題”則是統計i在左邊,但j在右邊的逆序對個數,對於右邊的每個j,統計左邊比他大的元素個數f(j),f(j)之和便是答案
8.2.2快速排序
快速排序是最快的通用內部排序算法。
劃分問題:把數組的各個元素重排後分成左右兩部分,使得左邊的任意元素都小於或等於右邊的任意元素
遞歸求解:把左右兩部分分別排序
合併問題:不用合併,因爲此時數組已經完全有序
8.2.3二分查找
int bsearch(int* A,int x,int y,int v){
int m;
while(x<y){
m=x+(y-x)/2;
if(A[m]==v)
return m;
else if(A[m]>v)
y=m;
else
x=m+1;
}
return -1;
}
下面的程序,當V存在時返回他出現的第一個位置。如果不存在,返回這樣一個下標i,在此處插入V後序列仍然有序
二分查找求下界
int lower_bound(int* A,int x,int y,int v){
int m;
while(x<y){
m=x+(y-x)/2;
if(A[m]>=v)
y=m;
else
x=m+1;
}
return x;
}