数据结构与算法 C 归并(Merge)排序(非递归)

7-18 排序(25 分)

给定N个(长整型范围内的)整数,要求输出从小到大排序后的结果。

本题旨在测试各种不同的排序算法在各种数据情况下的表现。各组测试数据特点如下:

数据1:只有1个元素;

数据2:11个不相同的整数,测试基本正确性;

数据3:103个随机整数;

数据4:104个随机整数;

数据5:105个随机整数;

数据6:105个顺序整数;

数据7:105个逆序整数;

数据8:105个基本有序的整数;

数据9:105个随机正整数,每个数字不超过1000。

输入格式:

输入第一行给出正整数N(≤10​5​​),随后一行给出N个(长整型范围内的)整数,其间以空格分隔。

输出格式:

在一行中输出从小到大排序后的结果,数字间以1个空格分隔,行末不得有多余空格。

输入样例:

11
4 981 10 -17 0 -20 29 50 8 43 -5

输出样例:

-20 -17 -5 0 4 8 10 29 43 50 981
非递归进行实现 思路很类似链表吧。方法也是俩个俩个的合并。
代码:
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 1000000
/** merge 排序 非递归实现**/
void swap(int x,int y) /**交换函数**/
{
    int z;
    z=y;
    y=x;
    x=z;
}
long long compare(long long x,long long y) /**比较函数**/
{
    if(x>=y)return 1;
    else return 0;
}
void conbine(long long *arr,int* idex,int x,int y) /**两个数组的合并(归并排序内用来合并的函数)**/
{
    int p1=x,p2=y,head,next;              /** x,y 分别是数组的第一个下标 实现 类似于链表 , head 是 头 next 是 正在插入时指针
                                            idex 是 记录 每个数的 指向下一个比他大的数的下标 **/


    if(compare(arr[x],arr[y]))             /**先找到 俩数组合并后的 第一个下标**/
    {
        head=next=y;
        p2=idex[p2];
    }
    else
    {
        head=next=x;
        p1=idex[p1];
    }
        while(p1>=0&&p2>=0)                  /** 俩数组比较 小的出去**/
        {
            if(compare(arr[p1],arr[p2]))
            {
                idex[next]=p2;
                p2=idex[p2];
            }
            else
            {
                idex[next] =p1;
                p1=idex[p1];
            }
            next=idex[next];
        }
        while(p1>=0)                          /**再把剩的全踢出去**/
        {
            idex[next]=p1;
            p1=idex[p1];
            next=idex[next];
        }
        while(p2>=0)
        {
             idex[next]=p2;
             p2=idex[p2];
             next=idex[next];
        }
        idex[next]=-head;                     /**合并后数组最后一个等于头下标的负值**/
}
void merge(long long *arr,int *idex,int n) /**归并排序**/
{
    int i=1,j,x,y,f;
    f=1;
    while(1)
    {


        while(i<=n&&idex[i]>0) i++;            /**循环 每次找俩个 数组来合并**/
            if(i<=n) x=i++;
            else x=0;
        while(i<=n&&idex[i]>0) i++;
            if(i<=n) y=i++;
            else y=0;
        //printf("%d %d\n",x,y);
        if(x&&y)                               /**找到俩个 合并**/
        {
            conbine(arr,idex,-idex[x],-idex[y]);
            f=0;
        }
        /*for(j=1;j<=n;j++)
            printf("%d ",idex[j]);
        printf("\n");*/
        if(f) break;                          /**f 意义是如果 最后 只找到一个 负数(头下标的负值)  就排好序了**/
        if(i>n)                        /** 小排序 一次后 进行第二次小排序**/
        {
            i=1;
            f=1;
        }
    }
}
void display(long long *arr,int *idex,int x)        /**用来输出 不多说了**/
{
    //printf("->");
    int f=1;
    while(x>=0)
    {
        if(f) f=0;
        else printf(" ");
        printf("%lld",arr[x]);
        x=idex[x];
    }
}
int main(){
    int n,i,j;
    scanf("%d",&n);
    long long *arr;
    arr = (long long *)malloc((n+2)*sizeof(long long));  /** 数组最好从 下标 1 开始 ,为了最后解决头下标负数 0 = -0的矛盾**/
    for(i=1;i<=n;i++)
    {
        scanf("%lld",&arr[i]);
    }
    int *idex;
    idex=(int*)malloc((n+2)*sizeof(int));
    for(i=1;i<=n;i++)
        idex[i]=-i;
    merge(arr,idex,n);
    //conbine(arr,idex,1,2);
    for(i=1;i<=n;i++)
    {
        if(idex[i]<0)
        {
            display(arr,idex,-idex[i]);
            break;
        }
    }

return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值