归并排序的递归实现

思路图来自:https://www.cnblogs.com/fanwencong/p/5910503.html

这里我们依然用顺序表来实现这个排序算法。

顺序表一样是0号位不用。

这里我们的归并排序是二路归并,思路就是把序列一直分解成两份,直至分到子序列的长度为1,那么显然子序列已经有序,然后再不停地将有序序列归并起来,最后实现排序。

下面上代码:

先是顺序表的接口与声明:

#define OVERFLOW 0
#define ERROR 0
#define FALSE 0
#define OK 1
#define TRUE 1

typedef struct {
    int * elem;//基址空间
    int length;//当前长度
    int size;//储存容量
    int increment;//扩容的增量
}SqList;
/*顺序表的接口*/
int InitSqList(SqList &L, int size, int inc);//初始化顺序表
int DestroySqList(SqList &L);//销毁顺序表L
int ClearSqList(SqList &L);//将顺序表清空
int SqListIsEmpty(SqList L);//判空函数
int GetElemSqList(SqList L, int i, int &e);//用e返回顺序表L中第i号元素
int SearchSqList(SqList L, int e);//在顺序表中查找元素e,若成功时返回该元素第一次出现的位置,否则返回-1
int PutElemSqList(SqList &L, int i, int e);//将L中第i个元素改为e
int AppendSqList(SqList &L, int e);//在L表添加元素e
int DeleteLastSqList(SqList &L, int &e);//删除L表的尾元素,并用参数e作为返回值
void TraverseSqList(SqList L);//遍历元素,并打印
                              /*随机数生成函数*/
int * RandomGenerate(int n);//生成个n个随机数的数组
                            /*测试函数*/

看算法:

void Merge(SqList & L1,SqList L2 , int i, int m, int n);//2路归并的归并操作,将L1的相邻有序区间i->m和m+1->n归并成i->n的有序序列储存到L2中。
void MSort(SqList L1, SqList L2, int i, int s, int t);//递归归并排序的递归排序操作,如果i为奇数,排序后的记录储存在L2否则存进L1里

int main()
{
      srand((unsigned)time(NULL));//加一句srand((unsigned)time(NULL));  打开随机触发器 与时钟频率同步
    SqList l;
    InitSqList(l,6,5);//默认加多一个内存
    int * testArray = RandomGenerate(6);
    int i;
    for (i = 0 ; i < 6; i++) {
        AppendSqList(l, testArray[i]);//默认从1号位开始加数字
    }
    printf("the original list:\n");
    TraverseSqList(l);

      //排序模块:
         SqList l2;
    InitSqList(l2, 6, 5);//辅助顺序表
    MSort(l, l2, 0, 1, l.length);//因为是排顺序表l,所以传入的i是偶数0
    DestroySqList(l2);
}    

void Merge(SqList & L1, SqList L2, int i, int m, int n) {//2路归并的归并操作,将L1的相邻有序区间i->m和m+1->n归并成i->n的有序序列储存到L2中。
    int j = i, k = m + 1, h = i;
    for (; j <= m, k <= n; h++) {
        if (L1.elem[j] <= L1.elem[k]) {//这个如果不加=就是不稳定的排序喔
            L2.elem[h] = L1.elem[j++];//哪个小就把哪个放过来
        }
        else {
            L2.elem[h] = L1.elem[k++];
        }
    }
    while (j <= m) {
        L2.elem[h++] = L1.elem[j++];
    }
    while (k <= n) {
        L2.elem[h++] = L1.elem[k++];
    }

}

void MSort(SqList L1, SqList L2, int i, int s, int t) { //递归归并排序的递归排序操作。这里是对L1进行排序如果i为奇数,排序后的记录储存在L2否则存进L1里
    int m;
    if (s == t) {  //终结条件
        if (i%2 == 1) {//奇数的话
            L2.elem[s] = L1.elem[s];
        }
    }
    else {
        m = (s + t) / 2;
        MSort(L1, L2, i + 1, s, m);//对前半部分递归排序
        MSort(L1, L2, i + 1, m+1, t);//对后半部分递归排序
        if (i % 2 == 1) {
            Merge(L1, L2, s, m, t);
        }
        else {
            Merge(L2, L1, s, m, t);
        }
    }
}
时间: 2024-07-30 14:56:29

归并排序的递归实现的相关文章

4.比较排序之归并排序(递归)

归并排序里运用到算法里很重要的一个思想——分治法:将原问题分解为几个规模较小但类似于原问题的子问题——<算法导论>.在每一层递归中都有3个步骤: 1.分解问题 2.解决问题 3.合并问题的解 举例待排序数组:{6, 5, 3, 1, 7, 2, 4},将它原始序列做分解. 可以经过不断的递归分解可以看到已经把原始数组序列不断分解为最小单位,接下来不妨将它们看做是二叉树的叶子节点. 将他们进行两两归并排序形成二叉树(也称为2路归并算法),可见二叉树的根节点即为最终序列.在这个过程中我们完成了剩余

归并排序的递归与非递归实现java

package com.edu.hpu.sort.merge; import com.edu.hpu.sort.Sort; public class MergeSort extends Sort { @Override public int[] doSort(int[] arr) { return mergeSort2(arr, 0, arr.length - 1); } @SuppressWarnings("unused") private int [] mergeSort(int

归并排序 分治+递归

0      1    2     3     4     5     6     7     8   //下标 {  9  ,  4  ,  3  ,  7  ,  3  ,  8  ,  2  ,  4  ,  8  }//通过mergesort函数递归 来切 开始的时候fir=0, las=8, mid=4  所以下标0-4,分为前组   5-8分为后组 {  9  , 4   ,  3  ,  7  ,  3 }{ 8   , 2   , 4  ,  8  } {  9   , 4  ,

Python归并排序(递归实现)

为什么归并排序如此有用?1. 快捷和稳定归并排序成为?一个非常棒的排序算法主要是因为它的快捷和稳定.它的复杂度即使在最差情况下都是O(n log n).而快速排序在最差情况下的复杂度是O(n^2),当n=20的时候,它比归并要慢4.6倍. 2.容易实现 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #coding:utf-8 def merge_sort(array):     length = le

排序算法之归并排序(递归实现)

[归并排序的思想] 归并排序的思想是如果子数组L和子数组R都是有序的,那么我们可以将其合并为一个有序数组:在归并排序中,首先将子数组的长度设为1,此时每个元素都是一个有序子数组,通过两两合并,我们可以得到若干个长度为2的有序子数组,然后对这些长度为2的子数组两两合并,就可以得若干个到长度为4的有序子数组--------如此下去,最终将合并为一个有序的数组. 下面用一个例子来说明: 假设有数组A[]={25 ,5 ,71, 1, 61, 11, 59 ,15, 48 ,19} 步骤一:(25)(5

归并排序(非递归,Java实现)

归并排序(非递归): public class MergeSort { /** * @param arr 待排序的数组 * @param left 本次归并的左边界 * @param mid 本次归并的中间位置,也就是分界线 * @param right 本次归并的右边界 * @param <T> 泛型 * @local aux 辅助空间(Auxiliary Space) */ private static <T extends Comparable<? super T>&g

归并排序(递归、非递归、以及自然归并排序)算法总结

注:本文所指归并排序指 二路归并排序. 归并排序是平均情况.最坏情况.最好情况时间复杂度都为O(Nlog2N)的稳定的排序算法.最近梳理了下归并排序的递归.非递归.以及自然归并排序算法. 归并排序的基础:将两个有序数组合并为一个有序数组,需要O(n)的辅助空间. 图片来自:https://www.cnblogs.com/chengxiao/p/6194356.html // array:待排序数组 //temparray: 临时数组 //startindex:起始下标 //middleindex

排序算法(四)——归并排序与递归

基本思想 分析归并排序之前,我们先来了解一下分治算法. 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出子问题的解,就可得到原问题的解. 分治算法的一般步骤: (1)分解,将要解决的问题划分成若干规模较小的同类问题: (2)求解,当子问题划分得足够小时,用较简单的方法解决: (3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解. 归并排序是分治算法的典型应用. 归并排序先将一个无序的N长数组切成N个有序子序列(只有一个数据的

归并排序与递归

基本思想 分析归并排序之前,我们先来了解一下分治算法. 分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出子问题的解,就可得到原问题的解. 分治算法的一般步骤: (1)分解,将要解决的问题划分成若干规模较小的同类问题: (2)求解,当子问题划分得足够小时,用较简单的方法解决: (3)合并,按原问题的要求,将子问题的解逐层合并构成原问题的解. 归并排序是分治算法的典型应用. 归并排序先将一个无序的N长数组切成N个有序子序列(只有一个数据的