归并排序的非递归实现

#include<stdio.h>
#include<stdlib.h>

//此部分直接硬写出来的,没参考网上代码,写的可能拙劣一点
//非递归
void sort(int num[], int n) //接受待排序数组和数组长度
{
    int tempnum = 1;
    int *temp;
    temp = (int*)malloc(n * sizeof(int)); //构建辅助数组,长度和待排序数组长度相同
    int count; //用于每趟排序检测是否全部更新完
    while (tempnum < n) //归并排序需要log(n)趟,tempnum每次自乘2,用于控制趟数
    {
        tempnum *= 2;
        count = 0;
        int countnum = n / tempnum;
        if (n%tempnum != 0) //查看每趟有几个集合(划分),不能整除的话自增一
        {
            countnum += 1;
        }
        int m = 1;
        for (int i = 0, j = i + tempnum / 2; count < n; i += tempnum / 2, j += tempnum / 2)
        {
            while (i < ((2 * m - 1)*tempnum / 2) && j < m*tempnum&&i < n&&j < n)
            {
                if (num[i] < num[j])
                {
                    temp[count] = num[i]; //可直接写成temp[count++]=num[i++],下面同理
                    i++;
                }
                else
                {
                    temp[count] = num[j];
                    j++;
                }
                count++;
            }

            if (i <  ((2 * m - 1)*tempnum / 2) && i < n) 
            //如果有一个点标没到达指定位置,则把这个数组的剩余部分复制到辅助数组,else if()同理
            {
                for (; i < ((2 * m - 1)*tempnum / 2); ++i)
                {
                    temp[count] = num[i];
                    count++;
                }
            }
            else if (j < m*tempnum&&j < n)
            {
                for (; j < m*tempnum&&j < n; ++j)
                {
                    temp[count] = num[j];
                    count++;
                }
            }
            m++;
        }
        for (int i = 0; i < n; ++i) //每趟排序完借助辅助数组更新待排序数组的值
                                    //此部分可在上面更新temp[]值的同时对num[]进行更新,而不必另外加一个for循环
        {
            num[i] = temp[i];
            //printf("%d ", num[i]);
        }
        //printf("\n");
    }
    free(temp);
}

//递归部分和网上大多数思路相同,此部分沿用下面博客的递归实现代码
//https://www.cnblogs.com/bluestorm/archive/2012/09/06/2673138.html
//递归
void merge(int num[], int start, int mid, int end)
{
    int n1 = mid - start + 1;
    int n2 = end - mid;
    int *left, *right;
    left = (int*)malloc(n1 * sizeof(int));
    right = (int*)malloc(n2 * sizeof(int));
    int i, j, k;

    for (i = 0; i < n1; i++)
        left[i] = num[start + i];
    for (j = 0; j < n2; j++)
        right[j] = num[mid + 1 + j];

    i = j = 0;
    k = start;
    while (i < n1 && j < n2)
        if (left[i] < right[j])
            num[k++] = left[i++];
        else
            num[k++] = right[j++];

    while (i < n1)
        num[k++] = left[i++];

    while (j < n2)
        num[k++] = right[j++];

    free(left);
    free(right);
}

void merge_sort(int num[], int start, int end)
{
    int mid;
    if (start < end)
    {
        mid = (start + end) / 2;

        merge_sort(num, start, mid); 
        merge_sort(num, mid + 1, end);
        merge(num, start, mid, end);
    }
}

int main()
{
    printf("---------非递归---------\n");
    int num[7] = { 49,38,65,97,76,13,27 };
    int n = 7;
    sort(num, n);
    for (int i = 0; i < n; ++i)
    {
        printf("%d ", num[i]);
    }
    printf("\n");
    printf("---------递归---------\n");
    int num2[7] = { 49,38,65,97,76,13,27 };
    merge_sort(num2, 0, 6);
    for (int i = 0; i < n; ++i)
    {
        printf("%d ", num2[i]);
    }
    return 0;
}

对非递归的函数的代码简化版:

#include<stdio.h>
#include<stdlib.h>

//非递归
void sort(int num[], int n)
{
    int tempnum = 1;
    int *temp;
    temp = (int*)malloc(n * sizeof(int));
    int count;
    while (tempnum < n)
    {
        tempnum *= 2;
        count = 0;
        int countnum = n / tempnum;
        if (n%tempnum != 0)
            countnum += 1;

        int m = 1;
        for (int i = 0, j = i + tempnum / 2; count < n; i += tempnum / 2, j += tempnum / 2)
        {
            for (int x = 0; x < n; ++x)
            {
                printf("%d ", num[x]);
            }
            printf("\n");
            while (i < ((2 * m - 1)*tempnum / 2) && j < m*tempnum&&i < n&&j < n)
            {
                if (num[i] < num[j])
                    temp[count++] = num[i++];
                else
                    temp[count++] = num[j++];   
            }
            if (i <  ((2 * m - 1)*tempnum / 2) && i < n)
            {
                while (i < ((2 * m - 1)*tempnum / 2))
                    temp[count++] = num[i++];
            }
            else if (j < m*tempnum&&j < n)
            {
                while (j < m*tempnum&&j < n)
                    temp[count++] = num[j++];
            }
            m++;
        }
        for (int i = 0; i < n; ++i)
        {
            num[i] = temp[i];
            printf("%d ", num[i]);
        }
        printf("\n");
    }
    free(temp);
}

int main()
{
    int num[7] = { 49,38,65,97,76,13,27 };
    int n = 7;
    sort(num, n);
    for (int i = 0; i < n; ++i)
    {
        printf("%d ", num[i]);
    }
    printf("\n");
    return 0;
}

可以看一下参考部分的博客,原作者的非递归算法实现的很简洁(虽然我还没有看)

参考:
https://www.cnblogs.com/bluestorm/archive/2012/09/06/2673138.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值