栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

归并排序算法(经典返回临时变量版)——C++

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

归并排序算法(经典返回临时变量版)——C++

归并排序算法思想主要是将两个有序数组合并成为一个有序数组,其关键点采用“分治思想”,“分”是二分法,将无序数组分割成为一个个有序数组,然后通过“治”  将两个有序数组合并成为一个有序数组。时间时间复杂度为为O(nlogn),空间复杂度是O(n)的常量级临时变量,是稳定排序算法。

归并排序主要实现思想:

采用“分治思想”,先“分”将整个无序数组先左边递归,再右边递归,类似二叉树先序遍历方法,将数组分为一个个有序数组;然后通过“治”将一个个有序数组通过合并merge方法组合成一个有序数组;

1.“分”vector merge(vector& nums, int start, int end);从起始和终止位置开始进行二分法。

vector Sorts::merge(vector& nums, int start, int end)
{
    if (start == end) //递归终止条件:如果起始下标等于结束下标,则终止递归
        return { nums[start] }; // 返回左边第一个元素
    int middle = (start + end) / 2; // 分治法,采用二分法,取中间下标开始左右递归,直到一个元素开始返回
    auto left = merge(nums, start, middle); // 先递归左边部分,退出该层后向右递归,直到一个元素
    print(left);
    auto right = merge(nums, middle + 1, end); // 先左边再右边递归取有序数组
    return merge(left, right); // 合并两个有序数组,然后继续回退到上一层左边或者右边递归,直到整个递归结束返回为止
}

一直遍历左边部分数据,然后再返回上层遍历右边数据,这样每次左右部分个子得到一个个或组合后的有序数据组。

即下图1所示,每次都打印遍历后左边的值,可以分析出,这个递归类似二叉树里面的先序遍历,每次总是先遍历左边元素回退上一层后再遍历右边最里层元素,图2打印数据更加印证这先遍历左边再遍历右边顺序。

图1  归并排序遍历后打印左边值

图2  归并排序遍历后打印右边值

 2.步骤1将无须数组分为一个个或一块块有序数组,这时需要将两个有序数组依次合并成一个有序数组vector merge(vector& nums1, vector& nums2);

合并的关键是用两个游走下标分别遍历两个数组,将其中一个较小元素放入新创建的数组里;当其中一个数组遍历完毕后,将剩余数组放入新数组后面则完成排序;如下代码所示:

vector Sorts::merge(vector& nums1, vector& nums2)
{
    int i1{ 0 }, i2{ 0 };
    vector mergeArr(nums1.size() + nums2.size(), 0);
    while (i1 < nums1.size() && i2 < nums2.size()) // 分别用两个下标遍历两个数组,取较小元素放到新数组,直到其中一个数组遍历完毕为止
    {
        //mergeArr[i1 + i2] = nums1[i1] <= nums2[i2] ? nums1[i1++] : nums2[i2++]; 这行在linux下可以,在msvc编译器段错误
        if (nums1[i1] <= nums2[i2]) // 取较小元素放入新数组
        {
            mergeArr[i1 + i2] = nums1[i1]; // 
            ++i1; // msvc ++ 好像跟gcc编译器的实现不一样,这里放在数组里面++会段错误
        }
        else
        {
            mergeArr[i1 + i2] = nums2[i2];
            ++i2;
        }
    }
    while (i1 < nums1.size()) // 将剩余数组放入新数组后面
    {
        mergeArr[i1 + i2] = nums1[i1];
        ++i1;
    }
    while (i2 < nums2.size()) // 将剩余数组放入新数组后面
    {
        mergeArr[i1 + i2] = nums2[i2];
        ++i2;
    }
    return mergeArr;
}

3.下面是完整的示例代码:

Sorts.h

#pragma once

#include 
#include 

using namespace std;

struct Sorts {    
    void merge(vector& nums);
    
    void print(vector& nums);

private:    
    vector merge(vector& nums, int start, int end);
    vector merge(vector& nums1, vector& nums2);
};

Sorts.cpp

#include "Sorts.h"

void Sorts::merge(vector& nums)
{
    if (nums.size() <= 1)
    {
        return;
    }
    auto tmpNums = merge(nums, 0, nums.size() - 1);
    nums = tmpNums;
}

void Sorts::print(vector& nums)
{
    for (const auto& it : nums)
        cout << it << ",";
    cout << endl;
}

vector Sorts::merge(vector& nums, int start, int end)
{
    if (start == end) //递归终止条件:如果起始下标等于结束下标,则终止递归
        return { nums[start] }; // 返回左边第一个元素
    int middle = (start + end) / 2; // 分治法,采用二分法,取中间下标开始左右递归,直到一个元素开始返回
    auto left = merge(nums, start, middle); // 先递归左边部分,退出该层后向右递归,直到一个元素
    auto right = merge(nums, middle + 1, end); // 先左边再右边递归取有序数组    
    return merge(left, right); // 合并两个有序数组,然后继续回退到上一层左边或者右边递归,直到整个递归结束返回为止
}

vector Sorts::merge(vector& nums1, vector& nums2)
{
    int i1{ 0 }, i2{ 0 };
    vector mergeArr(nums1.size() + nums2.size(), 0);
    while (i1 < nums1.size() && i2 < nums2.size()) // 分别用两个下标遍历两个数组,取较小元素放到新数组,直到其中一个数组遍历完毕为止
    {
        //mergeArr[i1 + i2] = nums1[i1] <= nums2[i2] ? nums1[i1++] : nums2[i2++]; 这行在linux下可以,在msvc编译器段错误
        if (nums1[i1] <= nums2[i2]) // 取较小元素放入新数组
        {
            mergeArr[i1 + i2] = nums1[i1]; // 
            ++i1; // msvc ++ 好像跟gcc编译器的实现不一样,这里放在数组里面++会段错误
        }
        else
        {
            mergeArr[i1 + i2] = nums2[i2];
            ++i2;
        }
    }
    while (i1 < nums1.size()) // 将剩余数组放入新数组后面
    {
        mergeArr[i1 + i2] = nums1[i1];
        ++i1;
    }
    while (i2 < nums2.size()) // 将剩余数组放入新数组后面
    {
        mergeArr[i1 + i2] = nums2[i2];
        ++i2;
    }
    return mergeArr;
}

main.cpp

 #include 
#include "Sorts.h"

using namespace std;

int main()
{
    vector nums = { 2,0,1,6,8,10,5,99,87,333,2,0,1 };
    Sorts sorts;
    sorts.print(nums);
    sorts.merge(nums);
    sorts.print(nums);
   
	return 1;
}

输出结果:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/444146.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号