首页 > 编程语言 >8645 归并排序(非递归算法)

8645 归并排序(非递归算法)

时间:2024-06-08 19:30:41浏览次数:15  
标签:归并 排序 nl 递归 int mid nr 8645

Description

用函数实现归并排序(非递归算法),并输出每趟排序的结果

输入格式

第一行:键盘输入待排序关键的个数n
第二行:输入n个待排序关键字,用空格分隔数据

输出格式

每行输出每趟排序的结果,数据之间用一个空格分隔

输入样例

10
5 4 8 0 9 3 2 6 7 1

输出样例

4 5 0 8 3 9 2 6 1 7
0 4 5 8 2 3 6 9 1 7
0 2 3 4 5 6 8 9 1 7
0 1 2 3 4 5 6 7 8 9

感觉非递归的归并排序有点难理解,我先理解了一下递归的归并排序,然后再理解非递归的就容易多了。递归方法的我也放在了后面。(最好是可以自己动手推一下,如果懒得动手可以看一下B站这个up主:纯情少狼雷格西 视频名字叫:二路归并排序算法 递归手动执行过程

做这个题,关键点就是写出merge排序函数,然后就是处理好每个划分与传入merge函数的下标的关系,理解记忆下来。

#include<stdio.h>

int a[1000],n;

void print() {
    for(int i = 0; i < n; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
}
//负责排序,就是把原数组中low-mid和(mid+1)-high这部分的数据排序
void merge(int low,int mid,int high)    //把每个要排序的分块视作左右两个数组之间的排序
{
    int nl,nr;
    nl=mid-low+1;    //左边数组的长度
    nr=high-mid;    //右边数组的长度
    int L[nl],R[nr];    //左右两个数组
    for(int i=0;i<nl;i++)    //用左右两个数组把原数组中对应要排序的位置的数据存储进来
    {
        L[i]=a[low+i];
    }
    for(int j=0;j<nr;j++)
    {
        R[j]=a[mid+1+j];
    }
    int i=0,j=0,k=0;
    //像合并顺序表那样把左右两个数组排好序
    while(i<nl&&j<nr)
    {
        if(L[i]<=R[j])
        {
            a[low+k]=L[i];
            k++;
            i++;
        }
        else
        {
            a[low+k]=R[j];
            k++;
            j++;
        }
    }
    while(i<nl)
    {
        a[low+k]=L[i];
        k++;
        i++;
    }
    while(j<nr)
    {
        a[low+k]=R[j];
        k++;
        j++;
    }
}
//负责分块
void split(int span)
{
    int nowlength=0;    //目前有多大长度 被划出来 根据分块大小来排序
    int low,mid,high;
    while(nowlength+span*2-1<n)    //分块大小为span,high下标多span*2-1个,high下标不能超n
    {
        low=nowlength;
        high=nowlength+2*span-1;
        mid=(low+high)/2;
        merge(low,mid,high);
        nowlength+=2*span;    //更新划出来的长度,同时也是下次排序的low
    }
    //存在没有完全划分的情况
    if(nowlength<n)    //要重新确定排序时需要的mid和high值
    {
        merge(nowlength,nowlength+span-1,n-1);    //high值就是最后一个
    }    //关于mid,因为是按1,2,4..这样划分来排的,所以nowlength+span-1就可以,可以自己推一下
}
//负责确定每个分块的大小:1,2,4,8...
void mergesort()
{
    int span=1;
    while(span<n)
    {
        split(span);
        print();
        span*=2;
    }
}

int main() {
    scanf("%d", &n);
    for(int i = 0; i <n; i++) {
        scanf("%d", &a[i]);
    }
    mergesort();
    return 0;
}

 下面是递归法的:

#include<stdio.h>

int a[1000],n;

void print() {
    for(int i = 0; i < n; i++) {
        printf("%d ", a[i]);
    }
    printf("\n");
}

void merge(int low,int mid,int high)
{
    int nl,nr;
    nl=mid-low+1;
    nr=high-mid;
    int L[nl],R[nr];
    for(int i=0;i<nl;i++)
    {
        L[i]=a[low+i];
    }
    for(int j=0;j<nr;j++)
    {
        R[j]=a[mid+1+j];
    }
    int i=0,j=0,k=0;
    //int flag=0;
    while(i<nl&&j<nr)
    {
        if(L[i]<=R[j])
        {
            a[low+k]=L[i];
            k++;
            i++;
        }
        else
        {
            a[low+k]=R[j];
            k++;
            j++;
            //flag=1;
        }
    }
    while(i<nl)
    {
        a[low+k]=L[i];
        k++;
        i++;
    }
    while(j<nr)
    {
        a[low+k]=R[j];
        k++;
        j++;
    }
    //if(flag==1) print();
}
//递归法
void mergesort(int low,int high)
{
    if(low<high)
    {
        int mid=(low+high)/2;
        mergesort(low,mid);
        mergesort(mid+1,high);
        merge(low,mid,high);
    }
}

int main() {
    scanf("%d", &n);
    for(int i = 0; i <n; i++) {
        scanf("%d", &a[i]);
    }
    mergesort(0,n-1);
    print();
    return 0;
}

标签:归并,排序,nl,递归,int,mid,nr,8645
From: https://blog.csdn.net/Caitlin_lee_/article/details/139532434

相关文章

  • Golang递归实现菜单分类
    packagemainimport( "fmt")//Menu菜单typeMenustruct{IDintParentIDintNamestringChildren[]Menu}//TreeList菜单typeTreeListstruct{IDintParentIDintNamestringChildren[]TreeList}//For......
  • 迭代与递归--你被递归搞晕过吗?
    前言算法中会经常遇见重复执行某个任务,那么如何实现呢,本文将详细介绍两种实现方式,迭代与递归。本文基于Java语言。一、迭代迭代(iteration),就是说程序会在一定条件下重复执行某段代码,直到条件不再满足。在Java语言中,可以理解为就是循环遍历,Java中有多种遍历方式,如for......
  • feapder框架爬取ks评论_递归的方式
    importrandomimportreimporttimefromfeapder.db.mysqldbimportMysqlDBimportfeapderdefis_number(string):pattern=re.compile(r'^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$')returnbool(pattern.match(string))classAirSpiderDemo(feapder.Ai......
  • 数据结构学习笔记-归并排序
    归并排序算法的设计与分析问题描述:设计并分析归并排序算法【算法设计思想】分割(Divide):从中间分割数组,使每个子数组包含一半的元素。这通过计算中点m来完成,通常是(l+r)/2,但为了防止大数溢出,使用l+(r-l)/2。解决(Conquer):递归地对两个子数组应用归并排序,直到......
  • 递归在多级数据结构中的简单应用
    哈喽,我是小码,半年多没更新了,这段时间换了新工作,工作也很忙。后续会尽量多写点,坚持确实是一件很难,很酷的事情。最近在公司负责开发商品有关的开发,商品包含类型、款式等属性,而类型可能有一级类型、二级类型甚至是三级类型,针对这种多级分类,这就就不好使用简单的查询了。之前也写了一......
  • Java 递归查询所有子节点id实现方法
    首先,我们需要创建一个方法来实现查询所有子节点id的功能。//定义一个方法,输入参数为父节点id和节点列表,返回值为该父节点下的所有子节点idpublicList<Long>getAllChildIds(LongparentId,List<Node>nodeList){List<Long>childIds=newArrayList<>();getAllC......
  • 顺序表应用7:最大子段和之分治递归法
    Description给定n(1<=n<=50000)个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时定义子段和为0,依此定义,所求的最优值为:Max{0,a[i]+a[i+1]+…+a[j]},1<=i<=j<=n。例如,当(a[1],a[2],a[3],a[4],a[5],a......
  • 【Android面试题】请你分别采用递归和非递归对二叉树进行遍历?
    请你分别采用递归和非递归对二叉树进行遍历?这道题想考察什么?1、二叉树的基本原理和遍历的方法?考察的知识点二叉树遍历的基本概念、二叉树的基本原理考生如何回答二叉树的基本概念当然可以!二叉树是一种常见的数据结构,它由一组称为节点的元素构成。每个节点可以有零个......
  • Day14 | 二叉树递归遍历
    递归遍历(必须掌握)二叉树的三种递归遍历掌握其规律后,其实很简单题目链接/文章讲解/视频讲解:https://programmercarl.com/二叉树的递归遍历.html注意前中后指的是根节点在前、中、后次序进行遍历。前序遍历#Definitionforabinarytreenode.#classTreeNode:#de......
  • 数组迭代方法和归并方法总结
    一、迭代方法(对数组每一项都运行)每个方法接受两个参数(以每一项为参数运行的函数,作为函数运行上下文的作用域对象(可选))传给每个方法的函数接收三个参数(数组元素,元素索引,数组本身)1.filter():函数返回true的项会组成数组后返回。(过滤函数,将数组中满足条件的项组成新数组后返回)。2.......