版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wyn126/article/details/81698558
归并排序算法思路
首先让数组中的每一个数成为长度为1的有序区间,让后将相邻的长度为1的有序区间进行合并,得到最大长度为2的有序区间,接下来再把相邻有序区间进行合并,得到相邻长度为4的有序区间……最后将剩下的所有有序区间进行合并,直到让数组中的所有数合并成为一个有序区间。归并排序的实现需要开辟一个新的数组来保存合并之后的值
用图解释如下:
代码实现如下:
#include<iostream>
#include<assert.h>
#include<string.h>
using namespace std;
void Merge(int *arr, int *tmp, int begin1, int end1, int begin2, int end2)//合并数组
{
int pos = begin1;//pos用来记录原始数组当前所在的位置
int index = begin1;//index用来记录新开辟数组到当前所在的位置
while (begin1 <= end1&&begin2 <= end2)//比较两个有序区间值的大小,对有序区间进行合并
{
if (arr[begin1] < arr[begin2])
{
tmp[index++] = arr[begin1++];
}
else //arr[begin1] > arr[begin2]
{
tmp[index++] = arr[begin2++];
}
}
while (begin1 <= end1)//对部分有序区间进行合并
{
tmp[index++] = arr[begin1++];
}
while (begin2 <=end2)
{
tmp[index++] = arr[begin2++];
}
memcpy(arr + pos, tmp + pos, sizeof(int)*(end2 - pos + 1));
}
//分裂数组
void _Merge(int *arr, int *tmp, int left, int right)
{
if (left >= right)
{
return;
}
int mid = left + (right - left) / 2;
_Merge(arr, tmp, left, mid);
_Merge(arr, tmp, mid+1,right);
Merge(arr, tmp, left, mid, mid + 1, right);
}
void MerageSort(int *arr, int sz)
{
assert(arr);
int *tmp = new int[sz];
_Merge(arr, tmp, 0, sz - 1);
delete[]tmp;
}
void Printf(int arr[], int sz)
{
assert(arr);
for (int i = 0; i < sz; i++)
{
cout << arr[i]<<" ";
}
}
int main()
{
int arr[] = { 90, 10, 50, 80, 30, 70, 40, 60, 20 };
int sz = sizeof(arr) / sizeof(arr[0]);
MerageSort(arr, sz);
Printf(arr, sz);
system("pause");
}
时间复杂度&&空间复杂度分析
- 时间复杂度:设数组长为N,由二分法可只将数组划分为小部分一共需要logN步,每一步都是合并有序数组的过程,时间复杂度为O(N),所以总的时间复杂度为Nlog(N)
- 因为归并排序每次都是在相邻的数组上进行操作,所以归并排序在时间复杂度为Nlog(N)(快速排序,堆排序,归并排序,希尔排序中)的几种排序方法中效率是最高的。
- 空间复杂度为:O(N),开辟了一块和原数组长度相等的新数组