目录
前言:
学习高级排序之前,我们学过几个简单排序:冒泡排序,(直接)插入排序,选择排序,他们对于数据量不是特别大的还是能够胜任,时间复杂度为O(n²),空间复杂度为O(1),这也使得他们在处理大量数据时浪费较多时间,因此我们可以使用时间复杂度更低的高级排序。
高级排序有以下几种常用的:归并排序,快速排序,堆排序,计数排序,桶排序。
归并排序属于高级排序中的一种,其特点明显,使用的是分治思想:"分"指的是将数组分割为两个子数组,并使用递归进行对半分,直到子数组的长度变为1,无法再分割为止。接着通过"治"(合并操作),将这些子数组逐层合并,确保每一层合并后的数组都是有序的。这种分治策略使得归并排序具有稳定性和高效性,是一种常用且有效的排序算法。
例题要求:
将无序序列9,6,2,10,4,5,8,7使用归并排序的方式排序
9 6 2 10 4 5 8 7
排序结果:
2 4 5 6 7 8 9 10
代码示例:
#include <stdio.h>
#include <string.h>
int merge(int arr[],int L,int M,int R)//治
{
//从中间对半分开,求左右数组长度和数组
int L_size=M-L;
int R_size=R-M+1;
int left[L_size];
int right[R_size];
for(int i=L;i<M;i++)
{
left[i-L]=arr[i];
}
for(int i=M;i<=R;i++)
{
right[i-M]=arr[i];
}
//左右数组将小的先放进原先数组,以此类推
int i = 0,j = 0,k = L;
while(i<L_size&&j<R_size)
{
if(left[i]<right[j])
{
arr[k]=left[i];
i++;
k++;
}
else
{
arr[k]=right[j];
j++;
k++;
}
}
//未进行比较的(当一个数组的元素全部已放入,就无需比剩下一个数组的元素了,因为数组原先已经排好顺序)直接放入
while(i<L_size)
{
arr[k]=left[i];
i++;
k++;
}
while(j<R_size)
{
arr[k]=right[j];
j++;
k++;
}
}
void mergesort(int arr[],int L,int R)//归并排序,分
{
if(L==R)
{
return;
}
else
{
int M=(L+R)/2+1;
mergesort(arr,L,M-1);
mergesort(arr,M,R);
merge(arr,L,M,R);
}
}
int main()
{
int arr[]={9,6,2,10,4,5,8,7};
int L=0,R=sizeof(arr)/sizeof(arr[0])-1,M=(L+R)/2+1;
mergesort(arr,L,R);
for(int i=0;i<=R;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
解释:
复杂度:
时间复杂度:O(nlogn)(无论好坏)
空间复杂度:O(n)(这是因为归并排序的合并操作需要一个与原数组相同大小的临时数组来存储合并后的结果,最多需要额外的 O(n) 空间。)
稳定性 :
稳定
NO.44
<C语言算法>