您的位置:首页 > 其它

算法基础:归并排序算法原理与实现

2017-02-24 17:07 155 查看
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,归并排序将两个已排序的表合并成一个表。

归并排序基本原理

通过对若干个有序结点序列的归并来实现排序。所谓归并是指将若干个已排好序的部分合并成一个有序的部分。

归并排序基本思想

将待排序序列R[0...n-1]看成是n个长度为1的有序序列,将相邻的有序表成对归并得到n/2个长度为2的有序表
将这些有序序列再次归并,得到n/4个长度为4的有序序列
如此反复进行下去,最后得到一个长度为n的有序序列。

在具体的合并过程中,设置 i,j 和 p 三个指针,其初值分别指向这三个记录区的起始位置。合并时依次比较 array[i] 和 array[j] 的关键字,取关键字较小(或较大)的记录复制到 temp[p] 中,然后将被复制记录的指针 i 或 j 加 1,以及指向复制位置的指针 p加 1。重复这一过程直至两个输入的子序列有一个已全部复制完毕(不妨称其为空),此时将另一非空的子序列中剩余记录依次复制到 array 中即可。

若将两个有序表合并成一个有序表,称为2-路归并

举例说明"归并排序的排序过程"

待排序列(14,12,15,13,11,16)

假设我们有一个没有排好序的序列,那么首先我们使用分割的办法将这个序列分割成一个个已经排好序的子序列。然后再利用归并的方法将一个个的子序列合并成排序好的序列。分割和归并的过程可以看下面的图例。


先"分割"再"合并"

从上图可以看出,我们首先把一个未排序的序列从中间分割成2部分,再把2部分分成4部分,依次分割下去,直到分割成一个一个的数据,再把这些数据两两归并到一起,使之有序,不停的归并,最后成为一个排好序的序列。

实现代码:

#include<stdio.h>
#include<stdlib.h>
typedef int Item;
#define key(A) (A)
#define less(A,B) (key(A)<key(B))
#define exch(A,B) {Item t=A;A=B;B=t;}
#define compexch(A,B) if(less(B,A)) exch(A,B)
int aux[10000];
void merge(Item a[],int l,int m,int r)
{
int i,j,k;
for(i=l;i<=m;i++) aux[i]=a[i];
for(j=r;j>m;j--) aux[m+r-j+1]=a[j];
for(i=l,j=r,k=l;k<=r;k++)
{
if(less(aux[i],aux[j]))
a[k]=aux[i++];
else a[k]=aux[j--];
}
}
void mergeSort(Item a[],int l,int r)
{
if(r<=l) return;
int m=(l+r)/2;
mergeSort(a,l,m);
mergeSort(a,m+1,r);
merge(a,l,m,r);
}
int main(int argc,char *argv[])
{
int N=atoi(argv[1]);
Item *a=(Item*)malloc(N*sizeof(Item));
for(int i=0;i<N;i++)
a[i]=1000*(1.0*rand()/RAND_MAX);
for(int i=0;i<N;i++)
printf("%3d ",a[i]);
printf("\n");
mergeSort(a,0,N-1);
for(int i=0;i<N;i++)
printf("%3d ",a[i]);
printf("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  归并排序 算法