归并排序
Merge Sort 归并排序
归并排序就是不断的将自己原有的序列从中间砍开,然后不断的从两边选出小的那个数放入另一个数组中。
例如:8 5 9 2 6 3 7 1 10 4 这个序列我们就可以将他砍成两半。
步骤一:8 5 9 2 6 | 3 7 1 10 4 排序数组:
步骤二:8 5 9 2 6 | 3 7 1 10 4(3和8比较3更小所以选出3来)排序数组:3
步骤三:8 5 9 2 6 | 3 7 1 10 4(7和8比较7更小所以选出7来)排序数组:3 7
步骤四:8 5 9 2 6 | 3 7 1 10 4(1和8比较1更小所以选出1来)排序数组:3 7 1
步骤五:8 5 9 2 6 | 3 7 1 10 4(8和10比较8更小所以选出8来)排序数组:3 7 1 8
步骤六:8 5 9 2 6 | 3 7 1 10 4(5和10比较5更小所以选出5来)排序数组:3 7 1 8 5
步骤七:8 5 9 2 6 | 3 7 1 10 4(9和10比较9更小所以选出9来)排序数组:3 7 1 8 5 9
步骤八:8 5 9 2 6 | 3 7 1 10 4(2和10比较2更小所以选出2来)排序数组:3 7 1 8 5 9 2
步骤九:8 5 9 2 6 | 3 7 1 10 4(6和10比较6更小所以选出6来)排序数组:3 7 1 8 5 9 2 6
步骤十:8 5 9 2 6 | 3 7 1 10 4(将剩下的全部添加到数组末尾)排序数组:3 7 1 8 5 9 2 6 10 4
这样不难看出可以保证当这个序列被分割成两半以后,进行这样的合并,可以抱证前半段的每一个数在排序数组中相对于那些后半段的元素来说是相对有序的,所以假如被我们分割的前半段和后半段就已经有序了,那么我们合并后的数组就是有序的了。
所以我们可以借助分治的思想,进行排序。
8 5 9 2 6 3 7 1 10 4
/ \
8 5 9 2 6 3 7 1 10 4
/ \ / \
8 5 9 2 6 3 7 1 10 4
/ \ / \ / \ / \
8 5 9 2 6 3 7 1 10 4
不断的从底层进行合并就能保证每次合并的两个序列就都是有序的序列了,就可以完成本次排序。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 const int maxn = 1000 + 5; 6 7 int n; 8 int a[maxn]; 9 10 void merge(int l,int r,int mid){ 11 int left = l; 12 int right = mid+1; 13 int vlue[maxn],cnt = 0; 14 while(left <= mid && right <= r){ 15 if(a[left] <= a[right]){ 16 vlue[++cnt] = a[left]; 17 left++; 18 } 19 else { 20 vlue[++cnt] = a[right]; 21 right++; 22 } 23 } 24 while(left <= mid){ 25 vlue[++cnt] = a[left]; 26 left++; 27 } 28 while(right <= r){ 29 vlue[++cnt] = a[right]; 30 right++; 31 } 32 int ll = l-1; 33 for(int i = 1;i <= cnt; i++){ 34 a[++ll] = vlue[i]; 35 } 36 return ; 37 } 38 39 void merge_sort(int l,int r){ 40 if(l == r)return ; 41 int mid = (l+r)>>1; 42 merge_sort(l,mid); 43 merge_sort(mid+1,r); 44 merge(l,r,mid); 45 } 46 47 int main(){ 48 int n; 49 scanf("%d",&n); 50 for(int i = 1;i <= n; i++){ 51 scanf("%d",&a[i]); 52 } 53 merge_sort(1,n); 54 for(int i = 1;i <= n; i++){ 55 printf("%d ",a[i]); 56 } 57 }