排序之归并排序

9 篇文章 0 订阅

归并排序也是基于比较排序的一种,采用分治模式,拆分成简单同类子问题,然后再合并。

伪代码如下:

MERGE-SORT(A, p, r)

if p < r
    q = floor((p + r) / 2)
    MERGE-SORT(A, p, q)
    MERGE-SORT(A, q + 1, r)
    MERGE(A, p, q, r)

MERGE(A, p, q, r)

n1 = q - p + 1
n2 = r - q
let L[1..n1 + 1] and R[1..n2 + 1] be new arrays
for i = 1 to n1
    L[i] = A[p + i - 1]
for j = 1 to n2
    R[j] = A[q + j]
L[n1 + 1] = infinite
R[n2 + 1] = infinite
i = 1
j = 1
for k = p to r
    if L[i] <= R[j]
        A[k] = L[i]
        i = i + 1
    else
        A[k] = R[j]
        j = j + 1

分析:

说明:(A, p, r)为列表A的下标p到下标r之间的子列表。

a.主程序MERGE-SORT将主问题每次分解成两个相同类型的子问题,直到分解成只有一个元素。然后再进行合并。

b.子程序MERGE将两个已排好序的子列表进行合并。首先新建两个列表,大小为两个子列表的大小加1,分别存储两个需要合并的子列表,然后在最后一个多的元素赋值一个哨兵元素,该元素需大于所有比较的元素。此时,用时: θ(n) 。因为每个子列表都是事先排好了序(第一次只有一个元素,相当于排好了序),所以,依次比较最末的两个元素,把小的放进源列表里。这样只需 θ(n) 次比较就能填满合并后的列表。

c.由于每次合并花费 θ(n) 的时间,一共有 lg(n) 次合并(每次划分一半,需要 lg(n) 次划分才能把n个元素划分完)。所以归并排序的时间复杂度为: θ(nlg(n)) 。相比于插入排序优化了时间复杂度。

d.但在合并过程中每次合并需要新建数组用于存放需要排序的数组,所以增加了空间复杂度。

C++代码实现

#include<iostream>
using namespace std;

#define MAX 999999
int* merge_sort(int*, int, int);
int* merge(int*, int, int, int);

int main()
{
    int A[] = {2, 3, 6, 23, 3, 14, 0, 7, 32, 5, 3};
    int length = sizeof(A)/sizeof(int);
    merge_sort(A, 0, length - 1);
    for(int i = 0; i < length; i++)
    {
        cout<<A[i]<<" ";
    } 
    cout<<endl;
    return 0;
}

int* merge_sort(int* A, int p, int r)
{
    if(p < r)
    {
        int q = (p + r) / 2;
        merge_sort(A, p, q);
        merge_sort(A, q + 1, r);
        merge(A, p, q, r);
    }
    return A;
}


int* merge(int* A, int p, int q, int r)
{
    int n1 = q - p + 1;
    int n2 = r - q;
    int *L = new int[n1 + 1];
    int *R = new int[n2 + 1];
    for(int i = 0; i < n1; i++)
    {
        L[i] = A[p + i];
    }
    for(int i = 0; i < n2; i++)
    {
        R[i] = A[q + i + 1];
    }
    L[n1] = MAX;
    R[n2] = MAX;
    int i = 0,j = 0;
    for(int k = p; k <= r; k++)
    {
        if(L[i] <= R[j])
        {
            A[k] = L[i];
            i++;
        }
        else
        {
            A[k] = R[j];
            j++;
        }
    }
    delete [] L;
    delete [] R;
    return A;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值