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

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,归并排序将两个已排序的表合并成一个表。
   归并排序基本原理

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

归并排序基本思想

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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值