A,归并排序:该算法是分治法的一个应用,先将整个待排序列分成若干子序列,然后使每个子序列有序,再使字序列之间有序,最终使整个序列有序。
B,算法原理:
1)假设我们采用二路归并对{a1,a2,a3,a4,...,an}进行排序;
2)首先将整个序列分成若干段,每段包好两个元素,即{a1,a2},{a3,a4},{a5,a6},{a7,a8}...;
3)然后分别对每个子序列排序(可以采用插入排序等),然后再将已排好序的子序列两两进行合并排序,如将排好序的
{a1,a2},{a3,a4}进行排序合并成4个元素{
a1,a2,a3,a4
};
4)然后再将4个元素排序合并成8个,直到完成整个序列的排序。
下面是一组乱序序列的排序过程:
C,算法实现:
#include "iostream"
#include "Math.h"
using namespace std;
int main()
{
void sort(int[], int, int);
int array[] = {9,3,8,13,15,1,7,10,2};
int n = sizeof(array)/sizeof(int*);
sort(array, 0, n - 1);
for(int i = 0; i < n; ++i)
cout<<array[i]<<" ";
cout<<endl;
return 0;
}
//归并排序
//array为待排序的数组,low代表数组第一个元素下标,high代表第二个元素下标
void sort(int array[],int low, int high)
{
void merge(int[], int, int, int);
if(low == high)
return;
int mid = ceil((high + low)/2);
//进行二路归并
sort(array, low, mid);
sort(array, mid+1, high);
merge(array, low, mid, high);
}
//合并函数
//合并时采用直接插入算法,因此没有额外申请空间
void merge(int array[], int low, int mid, inthigh)
{
int temp, index;
for(int i = mid + 1; i <= high; ++i)
{
index = i - 1;
temp = array[i];
while(array[index] > array[i] && index >=low)--index;
for(int j = i; j > index + 1; --j)
array[j] = array[j-1];
array[index+1]=temp;
}
}
运行结果:
D,复杂度分析
(a)时间复杂度:如果合并排序采用做法是申请一个新的数组存放两个合并的有序段,此时合并能在线性时间内完成,由上图树形结构可知共进行了logn(树的高度)次排序,因此该算法复杂度为O(nlogn)且与序列初始状态无关。
(b)空间复杂度:假如合并算法在线性时间内完成,则空间复杂度为O(n);如果如同上述算法实现一样,合并排序使用直接插入排序,则此时空间复杂度为O(1)。