小白学算法2.5.1——归并排序(自底而上)

小白学算法2.5.1——归并排序(自底而上)

标签: 小白学算法


1.自底而上的归并排序算法

自顶而下是从大数组到小数组再到大数组,因为最后都是分解到一个元素的数组,所以可以直接从一个元素的数组开始合并,一一合二,二二合四……直到合并出需要排序的大数组,这就是自底而上的归并排序算法。两种归并的方式时间复杂度和空间复杂度一样,后者比起前者编写起来要简单一些。自顶而下和自底而上的思想在编程中的非常的重要。

2.自底而上的归并排序实现

#include "stdafx.h"
#include <STDIO.H>

class MergeSort
{
public: 
    void mergeSort(int* a, int n);//递归

private:
    void merge(int* a, int lo, int mid, int hi);//合并
    int min(int a, int b);

    int* aux;//辅助数组
};

void MergeSort::mergeSort(int* a, int n)
{
    aux = new int[n];
    for (int sz = 1; sz < n; sz += sz)//sz表示子数组大小
        for (int lo = 0; lo < n-sz; lo += sz+sz)//lo表示子数组索引
            merge(a, lo, lo+sz-1, min(lo+sz+sz-1, n-1));
    delete [] aux;
}

void MergeSort::merge(int* a, int lo, int mid, int hi)
{
    int i = lo, j = mid+1;
    for (int k =lo; k<=hi; k++)
        aux[k] = a[k];

    for (k = lo; k<=hi; k++)
    {
        if (i > mid)                a[k] = aux[j++];//左边用尽取右边元素
        else if (j > hi)            a[k] = aux[i++];//右边用尽取左边元素
        else if (aux[j] < aux[i])   a[k] = aux[j++];//哪边小取哪边
        else                        a[k] = aux[i++];
    }
}

int MergeSort::min(int a, int b)
{
    return a < b ? a : b;
}

int main(int argc, char* argv[])
{
    // 测试数组
    int num[10]= {12,54,23,67,86,45,97,32,14,65};
    int i;
    // 排序之前
    printf("Before sorting:\n");
    for (i=0; i<10; i++)
        printf("%3d",num[i]);
    printf("\n");
    // 进行归并排序
    MergeSort test;
    test.mergeSort(num, 10);
    printf("After sorting:\n");
    // 排序之后
    for (i=0; i<10; i++)
        printf("%3d",num[i]);
    printf("\n");
    return 0;
}
  • 重构mergeSort函数,删除sort函数
  • merge函数没有改变
  • 最后要用min函数是因为最后一次合并的第二个数组可能比第一个数组小,进行排序的数组长度不是2的幂时会产生此类情况
  • merge参数意义如下:

    • 斜线填充的方框表示子数组的第一个元素
    • 红的方框圈出了两个要合并的子数组
    • lolo+sz+sz-1表示合并数组的起始和结束位置
    • lo+sz-1表示中间的位置,偶数个元素的中间位置就是前半段的最后一个元素

3.总结

  • 自底而上的性质和自顶而下的性质基本一致
  • 自底而上的归并排序比较适合链表组织成的数据,因为不需要创建新的链表结点,只需要原地的组织链表的链接就行
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值