本算法是笔者研读算法导论分治内容伪代码所写,俗话说,它山之石,可以攻玉。算导对排序有非常详细的解释,而分治排序更是其中巧妙的一种排序算法。分治排序先把数组分成[l,mid]与(mid,r]两部分,多次划分直到每个部分只有1个元素。然后把这两部分进行比较排序。(由于上一次的排序,这两个分数组内部是有序的);
举例说数组:[7,3,5,4,6,2,1],定义INF = 100,大于数组每个元素
(1)、第一次划分 [7,3,5,4] , [6,2,1]
(2)、对[7,3,5,4]进行第二次划分 [7,3],[5,4]
(3)、对[7,3]划分[7],[3];
(4)元素只有一个后,返回到[7,3],依次比较两个部分里的数进行排序。[7],[3]比较排序后,[3,7]
(5)同理[5,4]排完后为[4,5];返回到[7,3,5,4],由于上一步排序,该数组为[3,7,4,5];3跟4比,3小,[3,...],7跟4比,4小,[3,4,...],7跟5比,5小[3,4,5,..],7跟INF比,7小,[3,4,5,7];其实两个分数组都有一个INF元素在末尾.([3,7,INF],[4,5,INF]);
(6)同理向上合并,最后得到结果
简而言之,分治排序就是先把数组不到二分,直到只剩下一个元素。然后向上合并进行比较排序。比较排序比较巧妙的地方在于增加了一个INF,方便比较。
#include<iostream> using namespace std; #define INF (100) //INF 为大于等于待排序数的一个数字 void mSort_part(int* a,int l,int mid,int r) { int len1,len2,i,j,k; len1 = mid - l + 2; len2 = r - mid + 1; //数组A的范围是[l,mid]并且加上一个INF数字. //数组B的范围是[mid+1,r],并且加上一个INF数字. int A[len1],B[len2]; k = l; for(i=0;i<len1-1;++i) A[i] = a[k++]; A[i] = INF; for(j=0;j<len2-1;++j) B[j] = a[k++]; B[j] = INF; i = j = 0; for(k=l;k<=r;++k) if(A[i] < B[j]) a[k] = A[i++]; else a[k] = B[j++]; } //分治 void mSort(int *a,int l,int r) { if(l < r) { int mid = (l+r)/2; //先分 mSort(a,l,mid); mSort(a,mid+1,r); //最后进行合并排序 mSort_part(a,l,mid,r); } } int main() { //test code int a[] = {7,10,9,2,6,8,5,1,4,3}; int n = sizeof(a) / sizeof(int); mSort(a,0,n-1); for(int i=0;i<n;++i) cout<<a[i]<<" "; cout<<endl; return 0; }