- 先说一下归并排序的基本思想,本人画图能力有限,在这里给大家推荐一个详细点的链接大家先看一下基本思想和传统实现的代码
传统实现的代码如下:
https://blog.csdn.net/ds19980228/article/details/82863531
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
//分组归并
void _Merge(int *a, int begin1, int end1, int begin2, int end2, int *tmp)
{
int index = begin1;
int i = begin1, j = begin2;
//注意:当划分的区间足够小时,begin1==end1,begin2==end2
while (i <= end1&&j <= end2){
if (a[i]<=a[j])
tmp[index++] = a[i++];
else
tmp[index++] = a[j++];
}
//将左边元素填充到tmp中
while (i <= end1)
tmp[index++] = a[i++];
//将右边元素填充的tmp中
while (j <= end2)
tmp[index++] = a[j++];
//将tmp中的数据拷贝到原数组对应的序列区间
//注意:end2-begin1+1
memcpy(a + begin1, tmp + begin1, sizeof(int)*(end2 - begin1 + 1));
}
//归并排序
void MergeSort(int *a, int left, int right, int *tmp)
{
if (left >= right)
return;
assert(a);
//mid将数组二分
int mid = left + ((right - left) >> 1);
//左边归并排序,使得左子序列有序
MergeSort(a, left, mid, tmp);
//右边归并排序,使得右子序列有序
MergeSort(a, mid + 1, right, tmp);
//将两个有序子数组合并
_Merge(a, left, mid, mid + 1, right, tmp);
}
//打印数组
void PrintArray(int *a, int len)
{
assert(a);
for (int i = 0; i < len; i++)
printf("%d ", a[i]);
printf("\n");
}
int main()
{
int a[] = { 10, 6, 7, 1, 3, 9, 4, 2 };
int *tmp = (int *)malloc(sizeof(int)*(sizeof(a) / sizeof(int)));
memset(tmp, -1, sizeof(a) / sizeof(int));
MergeSort(a, 0, sizeof(a) / sizeof(int)-1, tmp);
PrintArray(a, sizeof(a) / sizeof(int));
system("pause");
return 0;
}
上面的代码主要可以理解成分组以及归并两个过程主要是递归调用这两个函数:
MergeSort和_Merge
我们在原有的基础上可以实现代码的简化将分组和归并写在一个递归调用的函数中,代码如下:
void MergeSortHelp(vector<int>&data, vector<int>©, int start, int end) {
if (start == end)
return;
int mid = (start + end) / 2;
MergeSortHelp(copy, data, start, mid);
MergeSortHelp(copy, data, mid + 1, end);
int i = mid, j = end;
int index = end;
while (i >= start && j >= mid + 1) {
if (data[i] > data[j])
copy[index--] = data[i--]; //从小到大
//copy[index--] = data[j--];从大到小
else
copy[index--] = data[j--];//从小到大
//copy[index--] = data[i--];从大到小
}
for (; i >= start;)
copy[index--] = data[i--];
for (; j >= mid + 1; j--)
copy[index--] = data[j--];
}
vector<int> MergeSort(vector<int>&v) {
bool Invalid_Input = false;
vector<int>copy;
int len = v.size();
if (len <= 0) {
Invalid_Input = false;
return copy;
}
for (int i = 0; i < len; i++)
copy.push_back(v[i]);
MergeSortHelp(v, copy, 0, len - 1);
return copy;
}
在这段代码中需要注意的是在MergeSort函数中我们需要一个辅助的vector容器(copy),核心就在于递归调用MergeSortHelp函数的时候每次改变copy其实就对应于上一次递归调用的data,因此返回上一次调用的递归函数时其实data就变成了有序的,当然这里的有序并不是说整个data是有序的,因为我们一开始会把这个data分成两半,这里的有序指的是在这一次递归调用中每一半都是有序的,整体不一定有序,这样递归一直到最后一次,data在分界点的两端分别是有序,因此通过copy来调整,将这些值有序的放入copy中(不是data),最后返回值是copy!!!,如果你返回data你会得到一个分界点两端分别有序的数组。因为本人写代码的时候想着省事一点所以没有用数组,直接用的vector容器,觉得太繁琐,其实用数组肯定也可以的!有错的地方希望看到的大佬即使纠正。