基本思想
将待排序的元素序列分成两个长度相等的子序列,对每一个子序列排序,然后将他们合并成一个序列。合并两个子序列的过程称为二路归并。
归并排序核心步骤:
- 分组
- 归并
代码如下
- 递归
void _MergeData(int array[], int left, int mid, int right, int *temp)
{
//左闭右开区间
int leftL = left; int rightL = mid;
int leftR = mid ; int rightR = right;
int Index = left;
while (leftL < rightL && leftR < rightR)
{
//先当小的
if (array[leftL] < array[leftR])
{
temp[Index++] = array[leftL++];
}
else
{
temp[Index++] = array[leftR++];
}
}
while (leftL < rightL)
{
temp[Index++] = array[leftL];
++leftL;
}
while (leftR < rightR)
{
temp[Index++] = array[leftR];
++leftR;
}
}
void _MergeSort(int array[], int left, int right, int* temp)
{
//至少区间里有一个元素
//如果不加1程序在剩一个元素的时候,会一直往下递归,
//最终就会造成栈溢出
if (left + 1 < right)
{
int mid = left + ((right - left) >> 1);
//先递归排左边子序列
_MergeSort(array, left, mid, temp);
//递归排右边子序列
_MergeSort(array, mid , right, temp);
//左右区间都有序后,在进行合并数据
_MergeData(array, left, mid, right, temp);
//拷贝元素到旧空间
memcpy(array + left,temp + left, (right - left)*sizeof(array[0]));
}
}
void MergeSort(int array[], int size)
{
int *temp = (int *)malloc(sizeof(int)*size);
if (NULL == temp)
{
assert(0);
return;
}
_MergeSort(array, 0, size, temp);
free(temp);
}
- 非递归
//非递归
void MergeSortNor(int array[], int size)
{
int *temp = (int*)malloc(sizeof(int)*size);
if (NULL == temp)
{
assert(0);
return;
}
int gap = 1;
for (; gap < size; gap *= 2)
{
int i = 0;
for (; i < size; i += 2 * gap)
{
int begin = i;
int mid = begin + gap;
int right = mid + gap;
//如果越界,则将它们调整回来
if (mid > size)
mid = size;
if (right > size)
right = size;
_MergeData(array, begin, mid, right, temp);
}
memcpy(array, temp, sizeof(int)*size);
}
free(temp);
}
总结
- 时间复杂度为O(NlgN)
- 空间复杂度O(N)
- 归并排序是一种稳定的排序算法