归并排序的基本思想:
归并排序使用了分治(即分开治理)和归并操作的思想。
例如将一个数组分成多块组成,通过递归完成对每一部分的分开,判断条件:Start>=End时即分完一部分,进行return跳出操作。在对每一部分进行归并操作,完成排序。
Step1:通过递归进行拆分;
Step2:进行归并排序;
示例代码:
void MergeSort(int arr[], int start,int end)
{
if (start>=end)
//判断条件:可参考二分查找条件
//注:取等号时,长度为1无法再分
return;
int mid = (start + end) / 2;//找到数组中间位置mid
MergeSort(arr, start, mid);//对前一个数组进行归并排序
MergeSort(arr, mid + 1,end);//对后一个数组进行归并排序
Merge(arr, start, mid, end);
}
排序的过程,首先进行递归:
以一个长度为10的数组为例。Start初始为0,End初始为9,mid为(0+9)/2。
接下来对数组左侧开始进行递归:
将该数组进行赋值方便后续示例:
此时对0,1位置进行排序,需要临时开辟一个空间即一个长度为(end-start+1)的数组,利用该数组对原数组的分块进行排序,
注意:每次排序后都将临时空间的数放回原数组:
对该递归的上一步进行排序:
同理对上述操作的上一步进行排序:
此时左侧数组的排序已经完成了,右侧数组的排序和左侧排序的步骤相同:
直至最后一次归并过程:
至此归并排序全部排序完毕。
排序详细代码:
void Merge(int arr[], int start, int mid, int end)
{
int* pArr = new int[end - start + 1];//开辟辅助空间
int i = start;//左侧的部分起始下标
int j = mid + 1;//右侧的部分起始下标
int k = 0; //临时空间的数组pArr下标
while (i<=mid && j<=end)
{
if (arr[i] < arr[j])
{
pArr[k] = arr[i];
i++;
}
else
{
pArr[k] = arr[j];
j++;
}
k++;
}
while (i<=mid)//左侧没有走到结尾
{
pArr[k] = arr[i];
i++;
k++;
}
while (j<=end)//右侧没有走到结尾
{
pArr[k] = arr[j];
j++;
k++;
}
//临时空间的数组已经排序完成了
//将此数组传入原数组中
i = start;
k = 0;
while (k<end-start+1)
{
arr[i] = pArr[k];
i++;
k++;
}
delete[]pArr;
pArr = nullptr;
}
使用归并排序,先创建一个数组:
int arr[] = {5,4,7,5,4,2,5,7,9,7};
调用归并排序:
MergeSort(arr,0,9);
遍历原数组arr:
for (int nVal : arr) { cout << nVal << " "; } cout << endl;
结果: