递归排序
前置学习
了解排序的基本概念
点击传送门
原理
**归并排序(Merge Sort)**的基本思想是:将两个序列合并在一起,并且使之有序。
该算法是采用**分治法(Divide-and-Conquer)**的经典的应用。
归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并
实现
- 把长度为n的输入序列分成两个长度为n/2的子序列;
- 对这两个子序列分别采用归并排序;
- 将两个排序好的子序列合并成一个最终的排序序列。
- 在2-路归并排序算法中,由于需要进行递归调用,为了保证递归的顺利执行,按照一定的方法划分序列,直到子序列成为单个的元素,才开始对相邻的序列进行排序与归并。
代码
归并两个序列的算法
//归并两个序列的算法
void Merge(int* arr, int* temp, int start, int mid, int end)
{
int i = start, j = mid + 1, k = start;
//比较排序并将值赋给中间变量temp
while (i != mid + 1 && j != end + 1)
{
if (arr[i] >= arr[j])
temp[k++] = arr[j++];
else
temp[k++] = arr[i++];
}
//若一个序列指针走到最后,另一个指针为走到最后,直接复制
while (i != mid + 1)
temp[k++] = arr[i++];
while (j != end + 1)
temp[k++] = arr[j++];
//将中间变量数组中存储的值赋给原始数组
for (i = start; i <= end; i++)
arr[i] = temp[i];
}
递归调用归并算法
//递归调用归并算法
void MergeSort(int* arr, int* temp, int start, int end)
{
int mid;
if (start < end)
{
//取中间值将原序列分为两组
mid = (start + end) / 2;
MergeSort(arr, temp, start, mid);
MergeSort(arr, temp, mid + 1, end);
Merge(arr, temp, start, mid, end);
}
}
测试代码
int main()
{
//定义数组
int arr[10] = { 9,1,5,6,10,8,3,7,2,4 };
//数组元素个数
int len = sizeof(arr) / sizeof(arr[0]);
int temp[10] = { 0 };
//归并排序
MergeSort(arr, temp, 0, len - 1);
//打印数据
for (int i = 0; i < 10; i++)
printf("%d\n", arr[i]);
return 0;
}
复杂度分析
时间复杂度:
平均时间复杂度:O(n log n)
最好时间复杂度:O(n log n)
最坏时间复杂度:O(n log n)
空间复杂度:
O(n),需要数据元素大小的额外空间用于交换。
稳定性:
稳定排序