归并排序
来说说归并排序是啥?归并排序就是排序呗。啥,啥排序?归并呗。
哔bibibi(瞎哔哔)
好吧,归并排序,是创建在归并操作上的一种有效的排序算法,效率为O(nlogn)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分
治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。速度仅次于快速排序,为稳定排序算法,一般用
于对总体无序,但是各子项相对有序的数列,归并排序的比较次数小于快速排序的比较次数,移动次数一般多于快速排序的移动次数。
算法思想
该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶
段则将分的阶段得到的各答案"修补"在一起,即分而治之)。既然归并排序采用的是分治法,并且依托于归并操作,那么其思想肯定是分
而治之。我们知道归并操作是将两个有序的数列合并到一个有序的序列,那么对于一个无序的长序列,可以把它分解为若干个有序的子
序列,然后依次进行归并。如果我们说每一个数字都是单独有序的序列,那么只要把原始长序列依次分解,直到每个子序列都只有一个
元素的时候,再依次把所有的序列进行归并,直到序列数为1
综上可知:
归并排序其实要做两件事:
(1)“分解”——将序列每次折半划分。
(2)“合并”——将划分后的序列段两两合并后排序。
算法步骤
(1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
(2)设定两个指针,最初位置分别为两个已经排序序列的起始位置;
(3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
(4)重复步骤 3 直到某一指针达到序列尾;
(5)将另一序列剩下的所有元素直接复制到合并序列尾。
话不多说,上代码
#include <iostream>
#include <cstring >
#include <cstdio>
#include <cmath>
using namespace std;
//归并过程
void merge(int arr[], int l, int mid, int r){
int help[r-l+1];//辅助数组
int i = 0;
int lIndex = l;
int rIndex = mid+1;
while(lIndex <= mid && rIndex <= r){
help[i++] = arr[lIndex] < arr[rIndex] ? arr[lIndex++]:arr[rIndex++];
}
//左边和右边肯定有一边到头了,不可能同时,因为每次只移动一边
while(lIndex <= mid){
help[i++] = arr[lIndex++];
}
while(rIndex <= r){
help[i++] = arr[rIndex++];
}
//将排好序的辅助数组赋值给原始数组,不需要返回值
for(i = 0; i < r-l+1; i++){
arr[l+i] = help[i];
}
}
//递归
static void msort(int arr[], int l, int r){
if(l == r){
return;
}
int mid = (l + r) / 2;
//左半部分归并排序
msort(arr, l, mid);
//右半部分归并排序
msort(arr, mid+1, r);
//左右部分归并
merge(arr, l, mid, r);
}
//归并排序整个数组
void msort(int arr[], int n){
//如果数组为空或只有一个元素,不需要排序
if(arr == NULL || n < 2){
return;
}
msort(arr,0,n-1);
}
int main(){
int arry[100];
int n;
cin>>n;
for(int i=0; i<n; i++)
cin>>arry[i];
msort(arry, n);
for(int i=0; i<n; i++)
cout<<arry[i]<<" ";
return 0;
}

浙公网安备 33010602011771号