【数据结构】八大排序之归并排序算法

举报
修修修也 发表于 2024/09/30 16:50:50 2024/09/30
【摘要】 ​ 🦄个人主页:修修修也 🎏所属专栏:数据 结 构 ⚙️操作环境:Visual Studio 2022​编辑目录一. 归 并排序 简 介及思想 二. 归 并排序的代 码实现 三. 归 并排序的非 递归 代 码实现 四. 归 并排序的复 杂 度分析 📌 时间 复 杂 度 📌 空 间 复 杂 度 结语 一.归并排序简介及思想"归并"一词的中文含义就是合并,并入的意思,而在数据结构中的定义...

 

🦄个人主:修修修也

🎏所属专栏:数据

⚙️操作:Visual Studio 2022

​编辑


一. 并排序 介及思想

二. 并排序的代 码实现

三. 并排序的非 递归 码实现

四. 并排序的复 度分析

📌 时间

📌

结语


一.并排序介及思想

""一词的中文含义就是合并,并入的意思,而在数据构中的定将两个或两个以上的有序表合成一个新的有序表.

并排序(Merging Sort)就是利用并的思想实现的排序方法.

它的原理是:

      初始序列含有n个记录,可看成是n个有序的子序列,每个子序列的1,然后两两,得到(表示不小于x的最小整数)个2或1的有序子序列;再两两,......,如此重复,直至得到一个n的有序序列,种排序方法称2路并排序.

算法动图演示如下:

​编辑

算法逻辑演示:

​编辑


二.并排序的代码实现

算法实现:(以升序)

1. 将数中的n个数据看成n个有序子序列

2. 然后将其两两并到新数,得到+1或1或2的有序子序列,将新数的数据拷回原数.

3. 重复步2,直到并得到一个n的有序序列.

综上,归并排序的代码实现如下:

//归并递归子函数

void _MergeSort(int* a, int begin, int end, int* tmp)

{

    if ( begin >= end )

        return;




    int mid = (begin + end) / 2;

    

    //先递归后访问进行操作,类似于树的后序遍历

    _MergeSort(a, begin, mid, tmp);

    _MergeSort(a, mid+1, end, tmp);




    //递归到叶子数组后,开始归并

    int begin1 = begin, end1 = mid;

    int begin2 = mid + 1, end2 = end;

    int i = begin;




    while (begin1 <= end1 && begin2 <= end2)

    {

        if (a[begin1] < a[begin2])//循环将小值尾插进新数组

        {

            tmp[i++] = a[begin1++];

        }

        else

        {

            tmp[i++] = a[begin2++];

        }

    }




//防止合并时有数组没拷贝完

    while (begin1 <= end1)

    {

        tmp[i++] = a[begin1++];

    }




    while (begin2 <= end2)

    {

        tmp[i++] = a[begin2++];

    }




    //拷贝tmp回原数组

    memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));




}




//归并排序

void MergeSort(int* a, int n)//不写区间,因为该函数不递归自己,否则每次都要malloc

{

    //开数组

    int* tmp = (int*)malloc(sizeof(int) * n);

    if (tmp == NULL)

    {

        perror("malloc fail::\n");

        return;

    }




    _MergeSort(a, 0, n - 1, tmp);//归并递归子函数




    free(tmp);

}

三.并排序的非递归码实现

算法实现思路:(以升序为例)

       因为归并排序递归是将完整的数不断分割成只有一个元素的数进行归并的,那么我们实现递归的时候,就可以在一开始直接将数组视为n个只有一个元素的子序列进行归并,然后再按照两个两个元素的数组进,一直向上归并,直到并成一个有n个元素的有序数组为.

        归并排序在非递归实现时需要额外注意当n不是2的次方倍时归并数末尾的越界,并对此错误现象做出及的修正.

归并排序的非递归实现代码如下:

//归并排序非递归

void MergeSortNonR(int* a, int n)

{

    //开数组

    int* tmp = (int*)malloc(sizeof(int) * n);

    if (tmp == NULL)

    {

        perror("malloc fail::\n");

        return;

    }




    int gap = 1;




    while (gap < n)

    {

        for (int i = 0; i < n; i =i+ 2 * gap)

        {

            int begin1 = i, end1 = i + gap - 1;

            int begin2 = i + gap, end2 = i + 2 * gap - 1;




            //修正数组非2的次方倍数时的越界现象

            if (end1 >= n)

            {

                end1 = n - 1;

                begin2 = n;

                end2 = n - 1;

            }

            else if (begin2 >= n)

            {

                begin2 = n;

                end2 = n - 1;

            }

            else if (end2 >= n)

            {

                end2 = n - 1;

            }




            int j = i;

            while (begin1 <= end1 && begin2 <= end2)

            {

                if (a[begin1] < a[begin2])

                {

                    tmp[j++] = a[begin1++];

                }

                else

                {

                    tmp[j++] = a[begin2++];

                }

            }




            while (begin1 <= end1)

            {

                tmp[j++] = a[begin1++];

            }

            while (begin2 <= end2)

            {

                tmp[j++] = a[begin2++];

            }

        }

        memcpy(a, tmp, sizeof(int) * n);

        gap *= 2;

    }




    free(tmp);

}

四.并排序的复度分析

📌时间

从最开始的示意图我们可以看出,并排序一趟总共处理n个元素,而总共要处理logn趟,因此归并排序的最好,最坏,以及平均时间都是一样的,那就是O(nlogn).


📌

而我们在排序过程中需要一个和原数相同大小的临时来对数组进行归并排序,因此归并排序的O(n).


结语

希望并排序算法解能大家有所帮助,迎大佬留言或私信与我交流.

学海漫浩浩,我亦苦作舟!关注我,大家一起学,一起!

 相关文章推荐

【数据 构】八大排序之冒泡排序算法

【数据 构】八大排序之希 排序算法

【数据 构】八大排序之直接插入排序算法

【数据 构】八大排序之 简单选择 排序

【数据 构】八大排序之堆排序算法

【数据 构】八大排序之快速排序算法

【数据 构】八大排序算法之 并排序算法

【数据 构】八大排序之 数排序算法

数据构排序算法篇思维导图:

​编辑


​编辑

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。