【排序算法五】归并排序

归并排序

归并排序用到的思想是分治法,是分治法的典型应用。

步骤:

(1) 将待排序的数据,划分为一个一个小区间
(2)将小区间归并成一个比较大的区间,临时存储到一个空间内,
(3)最后将临时空间的数据拷贝到原来的存储空间中。

时间复杂度

时间复杂度为O(N lgN),空间复杂度为O(N)
归并排序是稳定的算法

代码实现

//合并
void Merge(int arr1[],int left,int mid,int right,int temp[]);
//拆分
void MSort(int arr1[], int left, int right, int temp[]);


void MergeSort(int arr1[],size_t size)
{
    int *temp = new int[size];
    memset(temp, 0, sizeof(int)* size);
    MSort(arr1,0,size-1,temp);
    delete[] temp;
}

void MSort(int arr1[], int left, int right, int temp[])
// arr1归并排序后放在arr1[]中,temp作为一个辅助空间
{
    if (left < right)
    {
        int mid = left + ((right - left) >> 1);
        MSort(arr1, left, mid, temp);
        MSort(arr1, mid + 1, right, temp);
        Merge(arr1, left, mid, right, temp); //合并到temp中,再把temp 拷贝到arr1中
        memcpy(arr1+left, temp+left, sizeof(arr1[0])*(right - left + 1)); //注意这里加left,不然破坏原来的数组,并且不能正常拷贝
    }
}

//合并
void Merge(int arr1[],int left,int mid,int right,int temp[]) //升序
// 相邻两个有序子序列的合并算法,arr1[low ,mid] 和arr1[mid+1,hight] 合并成有序,存放到temp中
{
    int i = left;  //控制左半部分
    int j = mid + 1; //控制右半部分
    int k = left;//arr2的下标 ,注意不可以是0,
    while (i <= mid && j <= right)
    {
        if (arr1[i] <= arr1[j])
        {
            temp[k++] = arr1[i++];
        }
        else
        {
            temp[k++] = arr1[j++];
        }
    }
    //跳出循环可能有剩余的有序
    while (i <= mid)
    {
        temp[k++] = arr1[i++];
    }
    while (j <= right)
    {
        temp[k++] = arr1[j++];
    }
}

非递归算法

这里写图片描述

看图直接看明白

非递归思想: 将数组中的相邻元素两两配对,用merge函数将他们排序, 构成n / 2组长度为2的排序好的子数组段,然后再将他们排序成长度为4的子数组段,如此继续下去,直至整个数组排好序。

void MergeSortNor(int arr[],size_t size)
{
    int *temp = new int[size];
    size_t left = 0;
    size_t right = size - 1;
    size_t gap = 1;
    while (gap < size)
    {
        for (size_t idx = 0; idx < size;idx += gap*2)
        {
            left = idx;
            size_t mid = left + gap - 1;
            right = mid + gap;
            if (mid >= size) //最后一次排序
                mid = size - 1;
            if (right >= size) //第二个序列不足,
                right = size - 1;
            Merge(arr,left,mid,right,temp);
            cout << left << " " << mid << " " << right << endl;
        }
        memcpy(arr,temp,sizeof(arr[0])*size);
        gap <<= 1;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值