归并排序
归并排序,是一种基于分治思想的一种有效的,稳定的排序算法。它的时间复杂度为O(nlogn),空间复杂度为T(n),这里主要讲述一下二路归并排序
对于归并排序,简单的分为三步走
划分问题:把序列分成左右两边元素尽量相等的两个序列
递归求解:把分出的两个序列分别排序
合并问题:把两个已经排序好的序列合并成一个
下面是图解
自己画的,可能丑了不要打我
首先是划分的过程,这一部分直接通过递归就能做到了
划分过程的代码
void MergeSort(int arr[],int left,int right)
{
if(left<right){
int mid = left + (right - left) / 2;
MergeSort(arr, left, mid);
MergeSort(arr, mid + 1, right);
Merge(rr, left, mid, right);
}
}
接下来就是合并过程的过程了
这里需要注意,在合并的过程中,我们需要提前把最后一个元素的后一位设立一个非常大的数,这样在比较的过程中才不会出错。
在两个被划分的序列分别设两个指针i,j分别指向leftArr和rightArr。如果leftArr[i]小于rightArr[j],把它写到arr数组后i++就行了,反之亦然
如下列图表示
这里的 i 所指向的值小于 j 所指向的,故把leftArr[i]的值赋给arr,然后执行i++,k++;就变成了下图
重复以上操作
直到 i 或者 j到了尾部就结束
下面就是代码实现
void Merge(int arr[],int left,int mid,int right)
{
int leftCnt = mid - left + 1;
int rightCnt = right - mid;
int* leftArr = new int[leftCnt];
int* rightArr = new int[rightCnt];
for (int i = 0; i < leftCnt; i++){
leftArr[i] = arr[left + i];
}
for (int i = 0; i < rightCnt; i++){
rightArr[i] = arr[mid + i + 1];
}
leftArr[leftCnt] = 0x3fffffff;
rightArr[rightCnt] = 0x3fffffff;
for (int i = 0, j = 0, k = left; k <= right; k++){
if(leftArr[i]<=rightArr[j]){
arr[k] = leftArr[i++];
}else{
arr[k] = rightArr[j++];
}
}
delete []leftArr;
delete []rightArr;
}