分治模式在每一层递归上都有三个步骤:
(1)分解(divide):将原问题分解成一系列子问题;
(2)解决(conquer):递归的解各个子问题。若子问题足够小,则直接求解;
(3)合并(combine):将子问题的结果合并成原问题的解。
合并排序(merge sort)算法完全依照了上述模式,直观的操作如下:
a.分解:将n个元素分成各含n/2个元素的子序列;
b.解决:用合并排序法对两个子序列递归地排序;
c.合并:合并两个已排序的子序列以得到排序结果。
假设子数组A[p...q]和A[q+1...r]都已排好序,并将它们合并成一个已排序的子数组代替当前子数组A[p...r]
伪代码实现如下:
Merge_Array(A,first,mid,last) //Merge(V[],first,mid,last) n1 <-- mid-first+1 n2 <-- last-mid Creat arrays L[1...n1+1] and R[1...n2+1] for i=1 to n1 do L[i] <-- A[first+i-1] //Left for j=1 to n2 do R[j] <-- A[mid+j] //Right L[n1+1] <-- ∞ R[n2+1] <-- ∞ i=1 j=1 for k=first to last do if L[i] <= R[j] then A[k] <-- L[i] i =i+1
else
A[k] <-- R[j] j = j+1
现在可以将Merge_Array过程作为合并排序中的一个子程序来使用,下面的过程Merge_Sort(A,first,last)对子数组
A[first...last]进行排序。如果平first>=last,则该数组至多只有一个元素,当然就是已排序。否则,分解步骤就计算
出一个下标mid,将A[first...mid]和A[mid+1...last],各含[n/2]个元素。
Merge_sort(A,first,last) if first<last then mid=[(first+last)/2] Merge_sort(A,first,mid) Merge_sort(A,mid+1,last) Merge_Array(A,first,mid,last)
代码实现如下:
#include<iostream> using namespace std; //合并排序的合并程序他合并数组Arr[]中位置为[first,mid] 和(mid,last] void Merge_Array(int A[],int first,int mid,int last) { int* tmp = new int[last-first+1]; int k=0; int i=first; int j=mid+1; while(i<mid+1&&j<last+1) { if(A[i]<=A[j]) tmp[k++]=A[i++]; else tmp[k++]=A[j++]; } while(i<mid+1) tmp[k++]=A[i++]; while(j<last+1) tmp[k++]=A[j++]; k=0; for(int m=first;m<last+1;m++) A[m]=tmp[k++]; delete tmp; tmp=NULL; } void Merge_Sort(int Arr[],int start,int end) { if(start<end) { int mid=(start+end)/2; Merge_Sort(Arr,start,mid); //左侧排序[first,mid] Merge_Sort(Arr,mid+1,end); //右侧排序[mid+1,last] Merge_Array(Arr,start,mid,end); //合并已排序的两个子数组 } } int main() { int a[8]={5,2,4,7,1,3,2,6}; Merge_Sort(a,0,7); for(int i=0;i<8;i++) printf("%d ",a[i]); return 0; }