归并排序
归并排序(MergeSort)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,
称为二路归并。
算法描述:
归并操作的工作原理如下:
第一步:申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
第二步:设定两个边界,最初位置分别为两个已经排序序列的起始位置
第三步:比较两个边界所指向的元素,选择相对小的元素放入到合并空间,并移动边界到下一位置
重复步骤3直到某一边界超出序列尾
将另一序列剩下的所有元素直接复制到合并序列尾
代码实现:
#include <stdio.h>
#include <stdlib.h>
void Merge(int arr[],int tmp[],int startIndex,int midIndex,int endIndex)
{
int leftIndex = startIndex;
int rightIndex = midIndex + 1;
int tmpIndex = startIndex;
while(leftIndex < midIndex + 1 && rightIndex < endIndex + 1)//如果左右边界没有越界
{
if(arr[leftIndex] > arr[rightIndex])//左边的元素值大
{
tmp[tmpIndex++] = arr[rightIndex++];
}
else
{
tmp[tmpIndex++] = arr[leftIndex++];
}
}
while(leftIndex < midIndex + 1)//右边越界
{
tmp[tmpIndex++] = arr[leftIndex++];
}
while(rightIndex < endIndex + 1)//左边越界
{
tmp[tmpIndex++] = arr[rightIndex++];
}
//将排序好之后的临时数组中的元素放回到原数组中
for(int i = startIndex;i < endIndex + 1;i++)
{
arr[i] = tmp[i];
}
}
void MyMerge(int arr[],int tmp[],int startIndex,int endIndex)
{
if(startIndex < endIndex)
{
int midIndex = (endIndex + startIndex) / 2;
MyMerge(arr,tmp,startIndex,midIndex);
MyMerge(arr,tmp,midIndex + 1,endIndex);
Merge(arr,tmp,startIndex,midIndex,endIndex);
}
}
void MergeSort(int arr[],int len)//时间复杂度O(nlog2^n) 空间复杂度O(n)
{
int *tmp = (int *)malloc(sizeof(int)*len);//动态申请一个临时数组
MyMerge(arr,tmp,0,len - 1);
}
void Show(int arr[],int len)
{
for(int i = 0;i < len ;i++)
{
printf("%d ",arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = {12,67,9,45,34,28,53,19,5,80};
int len = sizeof(arr) / sizeof(arr[0]);
MergeSort(arr,len);
Show(arr,len);
return 0;
}
运行结果: