归并排序
概念:
”归并“的含义是将两个或两个以上的有序表组合成一个新的有序表。假定待排序列表含有n个记录,则可将其视为n个有序的子表,每个子表的长度为1,然后两两归并,得到【n/2】个长度为2或1的有序表;继续两两归并…如此重复,直到合并成一个长度为n的有序表为止,这种排序方法称为2路归并排序。
2路归并排序代码(c语言)
- 思路:使用分治和递归的思想,Merge()函数负责将两段元素合并为一段元素,MergeSort()函数代表了归并排序,我们的基本思想是将整段元素分为两段:
low-mid;mid+1-high 分别把两段元素排序之后再合并这两段元素。以此递归下去,结果是先将一段元素分割到两两合并的地步,再逐渐以二倍长度合并,最终将整段合并。
完整代码如下:
#include<stdio.h>
#include<stdlib.h>
#define n 10
int A[n]={4,2,1,7,0,6,9,5,3,8};
int *B=(int *)malloc(sizeof(int)*n);//开辟辅助数组
void Merge(int A[],int low,int mid,int high) //合并相邻两段元素
{
int i,j,k;
for(i=low;i<=high;i++)//将A中指定合并范围的元素赋值到辅助数组B中
{
B[i]=A[i];
}
for(i=low,j=mid+1,k=low;i<=mid&&j<=high;k++)//将B中相邻的左右两段元素合并到A中
{
//逐个将较小元素放入A中
if(B[i]<B[j]) A[k]=B[i++];
else A[k]=B[j++];
}
//将剩余元素插入到尾部
while(i<=mid) A[k++]=B[i++];
while(j<=high) A[k++]=B[j++];
}
void MergeSort(int A[],int low,int high)//归并排序
{
if(low<high)//如果没有到两两分割的地步,则采用递归的方式进行先分割再合并
{
int mid=(high+low)/2;
MergeSort(A,low,mid);
MergeSort(A,mid+1,high);
Merge(A,low,mid,high);
}
}
main()
{
MergeSort(A,0,n-1);
int i=0;
for(i=0;i<n;i++)
{
printf("%d ",A[i]);
}
}
2路归并排序的算法性能分析:
- 空间复杂度:空间的消耗主要在于辅助数组B,而B的大小与原数组相同为N,所以空间复杂度为O(N);
- 时间复杂度:对于二路归并排序,显然需要分割logN次,即需要进行logN次排序,而每一趟排序的时间复杂度为O(N),所以算法的总时间复杂度为O(NlogN)
- 稳定性:Merge操作不改变相同关键字的相对次序,是稳定排序