【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现

这篇具有很好参考价值的文章主要介绍了【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、归并排序

归并排序是一种经典的排序算法,它使用了分治法的思想。下面是归并排序的算法思想:

  1. 递归地将数组划分成较小的子数组,直到每个子数组的长度为1或者0。
  2. 将相邻的子数组合并,形成更大的已排序的数组,直到最终得到一个完全排序的数组。

归并排序的过程可以分为三个步骤:拆分(Divide)、合并(Merge)和排序(Sort)。

  1. 拆分:将待排序的数组不断地划分为两个子数组,直到每个子数组的长度为1或者0。
  2. 合并:将相邻的子数组合并为一个较大的已排序数组,通过比较两个子数组的首元素,按照从小到大的顺序逐个将元素放入一个辅助数组。
  3. 排序:重复进行合并的过程,直到最终得到完全排序的数组。

归并排序的时间复杂度为O(nlogn),其中n是待排序数组的长度。空间复杂度为O(n),主要是由于需要使用一个大小与原始数组相同的辅助数组来存储合并的结果。

归并排序是一种稳定的排序算法,即相等元素的相对顺序在排序前后保持不变。在合并的过程中,如果遇到两个相等的元素,我们会先将来自前一个子数组的元素放入辅助数组,这样可以确保相等元素的相对顺序不会改变。

【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现,排序算法,算法,数据结构

【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现,排序算法,算法,数据结构

代码实现:

// 归并排序具体功能实现函数
void MergeSortFun(int* a, int* temp, int begin, int end)
{
    // 如果数组大小为1或者空,直接返回上一层
    if (begin >= end)
    {
        return;
    }
    
    // 划分数组,递归调用 MergeSortFun 对左右子数组进行排序
    int mid = (begin + end) / 2;
    MergeSortFun(a, temp, begin, mid);
    MergeSortFun(a, temp, mid + 1, end);
    
    // 合并两个有序子数组
    int begin1 = begin;
    int end1 = mid;
    int begin2 = mid + 1;
    int end2 = end;
    int i = begin;
    
    // 依次比较两个子数组的元素,将较小的元素放入辅助数组 temp 中
    while (begin1 <= end1 && begin2 <= end2)
    {
        if (a[begin1] < a[begin2])
        {
            temp[i++] = a[begin1++];
        }
        else 
        {
            temp[i++] = a[begin2++];    
        }
    }
    
    // 将剩余的元素放入辅助数组 temp 中
    while (begin1 <= end1)
    {
        temp[i++] = a[begin1++];
    }
    while (begin2 <= end2)
    {
        temp[i++] = a[begin2++];
    }
    
    // 将辅助数组 temp 中的元素拷贝回原数组
    for (i = begin; i <= end; i++)
    {
        a[i] = temp[i];
    }
}

// 归并排序入口函数
void MergeSort(int* a, int n)
{
    int begin = 0;
    int end = n - 1;
    
    // 创建大小为 n 的辅助数组 temp
    int* temp = (int*)malloc(sizeof(int) * n);
    
    // 调用 MergeSortFun 对数组 a 进行归并排序
    MergeSortFun(a, temp, begin, end);
    
    // 释放辅助数组 temp 的内存空间
    free(temp);
}

二、归并排序非递归实现 

归并排序可以使用非递归的方式实现,其算法思想如下:

  1. 将待排序的数组划分为多个大小为1的子数组。
  2. 分别对这些子数组进行两两合并,形成新的有序子数组。
  3. 不断重复步骤2,直到得到一个有序的数组。

具体的非递归实现过程如下:

  1. 首先,定义一个大小为n的辅助数组temp用于存储合并后的有序子数组。
  2. 设置一个变量gap初始值为1,表示每次合并的两个子数组的大小。
  3. 进行多轮合并,直到gap大于等于n。
    • 在每一轮合并中,将数组分为多个大小为gap的子数组,将相邻的两个子数组合并为一个有序子数组。合并时,使用双指针i和j分别指向两个子数组的起始位置,比较两个子数组对应位置上的元素大小,较小的元素放入temp数组中,同时移动指针,直到一个子数组遍历完成。将未遍历完的子数组中剩余的元素直接放入temp数组中。
    • 更新gap的值为2倍,继续下一轮合并。
  4. 最后一轮合并时,gap可能大于n,因此需要额外的判断和处理。
  5. 将temp数组中的元素拷贝回原数组中。

通过不断调整gap的大小,将待排序数组进行分组和合并操作,直到得到一个完全有序的数组。非递归实现的归并排序避免了递归带来的额外开销,提高了算法的效率。、

【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现,排序算法,算法,数据结构文章来源地址https://www.toymoban.com/news/detail-814473.html

 代码实现:

void mergesortnr(int* a, int* temp, int begin, int mid, int end)
{
    // 定义指针和索引
    int head1 = begin;
    int tail1 = mid;
    int head2 = mid + 1;
    int tail2 = end;
    int i = begin;

    // 合并两个有序子数组
    // [head1,tail1] 和 [head2,tail2] 归并
    while (head1 <= tail1 && head2 <= tail2)
    {
        // 比较两个子数组对应位置上的元素大小,较小的元素放入temp数组中
        if (a[head1] < a[head2])
        {
            temp[i++] = a[head1++];
        }
        else
        {
            temp[i++] = a[head2++];
        }
    }

    // 将第一个子数组中剩余的元素放入temp数组中
    while (head1 <= tail1)
    {
        temp[i++] = a[head1++];
    }

    // 将第二个子数组中剩余的元素放入temp数组中
    while (head2 <= tail2)
    {
        temp[i++] = a[head2++];
    }

    // 将temp数组中的元素拷贝回原数组中
    memcpy(a + begin, temp + begin, sizeof(int) * (end - begin + 1));
}

void MergeSortNR(int *a, int n) 
{
    // 创建辅助数组
    int* temp = (int*)malloc(sizeof(int) * n);
    int gap = 1;

    // 不断调整gap的大小,分组合并
    for (gap = 1; gap < n; gap *= 2)
    {
        // 对每一组进行合并
        for (int i = 0; i < n - gap; i += 2 * gap)
        {
            // 计算子数组的起始索引、中间索引和结束索引
            int begin = i;、
/*如果i + 2 * gap - 1大于等于数组长度n,说明当前的子数组已经超出了数组的范围,此时将结束索引end赋值为n - 1,即最后一个元素的索引。

如果i + 2 * gap - 1小于数组长度n,说明当前的子数组还在数组的范围内,此时将结束索引end赋值为i + 2 * gap - 1。*/
            int end = i + 2 * gap - 1 >= n ? n - 1 : i + 2 * gap - 1;
            int mid = i + gap - 1;

            // 调用mergesortnr函数合并子数组
            mergesortnr(a, temp, begin, mid, end);
        }
    }
}

到了这里,关于【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构】手撕归并排序(含非递归)

    目录 一,归并排序(递归) 1,基本思想  2,思路实现 二,归并排序(非递归) 1,思路实现 2,归并排序的特性总结: 1,基本思想 归并排序 (MERGE-SORT) 是建立在 归并操作 上的一种 有效的排序算法 ,该算法是采用 分治法(Divide and Conquer) 的一个非常典型的应用; 将 已

    2024年02月08日
    浏览(47)
  • 数据结构排序——详细讲解归并排序(c语言实现递归及非递归)

    上次是快排和冒泡:数据结构排序——详解快排及其优化和冒泡排序(c语言实现、附有图片与动图示意) 今天为大家带来归并排序 归并排序是一种分治算法,它将序列分成两个子序列,分别对 子序列进行排序 ,然后将排序好的子序列 合并起来 。这个过程可以 递归 地进行,

    2024年01月22日
    浏览(67)
  • 数据结构——排序算法——归并排序

    在第二个列表向第一个列表逐个插入的过程中,由于第二个列表已经有序,所以后续插入的元素一定不会在前面插入的元素之前。在逐个插入的过程中,每次插入时,只需要从上次插入的位置开始,继续向后寻找插入位置即可。这样一来,我们最多只需要将两个有序数组遍历

    2024年02月09日
    浏览(47)
  • 数据结构和算法笔记4:排序算法-归并排序

    归并排序算法完全遵循分治模式。直观上其操作如下: 分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。 解决:使用归并排序递归地排序两个子序列。 合并:合并两个已排序的子序列以产生已排序的答案。 我们直接来看例子理解算法的过程,下面是要排序

    2024年01月21日
    浏览(63)
  • 数据结构与算法—归并排序&计数排序

    目录 一、归并排序 1、主函数 2、递归实现 3、优化递归  4、非递归实现 5、特性总结: 二、计数排序 1、代码: 2、特性总结: 三、各种排序总结 时间空间复杂度汇总  基本思想: 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用 分治法 的一个非常典型的

    2024年02月04日
    浏览(47)
  • 数据结构算法--5 归并排序

    我们先看一下归并排序是怎么归并的  两个有序列表,有low指针指向2,high指针指向6,mid指针指向9 再建一个新列表,12,所以1放到列表,右指针右移一位,再比较2和3,2放入列表,左指针右移一位,以此类推,肯定有一部分列表率先没有数,这时将另一列表直接append进入新

    2024年02月11日
    浏览(47)
  • 数据结构与算法:归并排序

    在讲解归并排序前,我们先看到一个问题: 对于这样两个有序的数组,如何将它们合并为一个有序的数组? 在此我们处理这个问题的思路就是:开辟一个新的数组,然后分别安置一个指针在左右数组,利用指针遍历数组,每次对比将比较小的那个元素插入到数组的尾部。 像

    2024年01月21日
    浏览(45)
  • python算法与数据结构---排序和归并排序

    掌握归并排序的基本原理 使用python语言解答归并排序题目 原理及过程 将两个有序的数组合并成一个有序数组称为 从上往下分解:把当前区间一分为二,直至分解为若干个长度为1的子数组 从上往下的合并:两个有序的子区域两两向上合并; 体现了分治思想,稳定排序 复杂

    2024年01月21日
    浏览(72)
  • 【数据结构】 七大排序详解(贰)——冒泡排序、快速排序、归并排序

    ==冒泡排序(Bubble Sort)==也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会

    2024年02月09日
    浏览(123)
  • 【数据结构】排序算法(二)—>冒泡排序、快速排序、归并排序、计数排序

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.冒泡排序 2.快速排序 2.1Hoare版 2.2占坑版 2.3前后指针版 2.4三数取中对快速排序的优化 2.5非递归版 3.归

    2024年02月08日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包