非比较排序——归并排序

版权声明:本文为博主原创文章,未经博主允许不得转载。 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),开辟了一块和原数组长度相等的新数组

猜你喜欢

转载自blog.csdn.net/wyn126/article/details/81698558