归并排序(MERGE-SORT)

本文详细介绍了归并排序算法的工作原理及其实现过程。归并排序采用分治策略,递归地将序列分解为更小的部分,并通过合并已排序的子序列来产生最终排序结果。文章提供了详细的伪代码和C++实现代码。

归并排序算法完全遵循分治模式。直观上其操作如下:
分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。
解决:除非分解后得到的两个子序列的元素个数为1,否则继续使用归并排序递归地排序两个子序列。
合并:合并两个已排序的子序列以产生已排序的答案。
当待排序的序列长度为1时,递归“开始回升”,在这种情况下不要做任何工作,因为长度为1的每个序列都已排好序。

归并排序算法的关键操作是“合并”步骤中两个已经排序序列的合并。我们通过调用一个辅助过程MERGE(A, low, mid, high)来完成合并,其中A是一个数组,low、mid和high是数组下标,满足lowmid<high。该过程假设子数组A[low..mid]和A[mid+1..high]都已排好序。它合并这两个子数组形成单一的已排好序的子数组并代替当前的子数组A[low..high]。下面是过程MERGE(A, low, mid, high)的伪代码描述:

MERGE(A,low,mid,high)
1     n1=midlow+1
2     n2=highmid
3     let L[1..n1+1] and R[1..n2+1] be new arrays
4     for i=1 to n1
5    L[i]=A[low+i1]
6     for j=1 to n2
7    R[j]=A[mid+j]
8     i=1
9     j=1
10   for k=low to high
11  if L[i]R[j]  && i !=n1
12  A[k]=L[i]
13  i=i+1
14  else if R[j]L[i]  && j !=n2
12  A[k]=R[j]
15  j=j+1
16  if i==n1 || j==n2
17  break
18   if(i==n1)
19  for k=k to high
20  A[k]=R[j]
21  j=j+1
18   else if(j==n2)
19  for k=k to high
20  A[k]=L[i]
21  i=i+1

现在我们可以把过程MERGE作为归并排序算法中的一个子程序来用。下面的过程MERGE-SORT(A, p, r)排序子数组A[p..r]中的元素。若p≥r,则该子数组最多有一个元素,所以已经排好序。否则,分解步骤简单地计算一个下标q,将A[p..r]分成两个子数组A[p..q]和A[q+1..r],前者包含n/2个元素,后者包含n/2个元素。

MERGESORT(A,p,r)
1     if p<r
2    q=(p+r)/2
3    MERGESORT(A,p,q)
4    MERGESORT(A,q+1,r)
5    MERGE(A,p,q,r)

C++实现:

/*归并排序*/
#include <iostream>
using namespace std;

void MergeSort(int* a, int low, int high);
void Merge(int* a, int low, int mid, int high);

void main() {
    const int LENGTH = 5;
    int a[LENGTH] = { 75,34,93,42,61 };

    MergeSort(a, 0, 4);

    for(int i=0; i<LENGTH; i++)
        cout << a[i] << " ";

    system("pause");
}

void MergeSort(int* a, int low, int high) {
    if (low < high) {
        int mid = (low + high) / 2;
        MergeSort(a, low, mid);
        MergeSort(a, mid + 1, high);
        Merge(a, low, mid, high);
    }
}

void Merge(int * A, int low, int mid, int high) {
    int n_1 = mid - low + 1;
    int n_2 = high - mid;
    int * L = new int[n_1];
    int * R = new int[n_2];
    int i, j;
    for (i = 0; i < n_1; i++) {
        L[i] = A[low + i];
    }
    for (j = 0; j < n_2; j++) {
        R[j] = A[mid + j + 1];
    }
    i = 0;
    j = 0;
    int k;
    for (k = low; k <= high; k++) {
        if (L[i] <= R[j] && i < n_1) {
            A[k] = L[i];
            i++;
        }
        else if (R[j] <= L[i] && j < n_2) {
            A[k] = R[j];
            j++;
        }
        if (i == n_1 || j == n_2) {
            k++;
            break;
        }
    }

    if (i == n_1) {
        for (; k <= high; k++) {
            A[k] = R[j++];
        }
    }
    else if (j == n_2) {
        for (; k <= high; k++) {
            A[k] = L[i++];
        }
    }

    delete[] L, R;
    L = NULL;
    R = NULL;
}

程序执行结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值