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

来源:互联网 发布:穆雅斓淘宝店铺改名了? 编辑:程序博客网 时间:2024/05/23 00:41

小白学算法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.总结

  • 自底而上的性质和自顶而下的性质基本一致
  • 自底而上的归并排序比较适合链表组织成的数据,因为不需要创建新的链表结点,只需要原地的组织链表的链接就行
0 0
原创粉丝点击