一、算法的基本思想
归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
将待排序的元素分为两个长度相等的子序列,为每一个子序列排序,然后将他们合并成一个序列。合并两个子序列的过程叫做两路归并。
二、算法的具体步骤
(1)类似于快速排序,我们把待排序区间划分成两个长度想等的子区间。
(2)递归其子区间,直到区间里面的元素只剩下一个,我们认为这个子区间已经有序。
(3)当区间只剩下一个元素时候,每次将相邻两个区间合并成一个大的有序的区间,然后一层层往上返回。
(4)直到返回到第一层,整个区间已经有序。
合并的步骤:
(1)申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列。
(2)设定两个指针,最初位置分别为两个已经排序序列的起始位置。
(3)比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置。重复此操作,直到某一指针达到序列尾部。
(4)将另一序列剩下的所有元素直接复制到合并序列尾。
三、举例如下图
四、代码实现
递归方式
//归并排序
void MergeSort(int *arr, int size)
{
if (arr == NULL || size <= 0)
return;
int *tmp = new int[size];
_merge(arr, tmp, 0, size - 1);
delete[] tmp;
}
void _merge(int *arr, int *tmp, int left, int right)
{
if (left >= right)
return;
int mid = left + ((right - left) >> 1);
_merge(arr, tmp, left, mid);//递归划分左区间
_merge(arr, tmp, mid + 1, right);//递归划分右区间
Merge(arr, tmp, left, mid, right);//合并
}
void Merge(int *arr, int *tmp, int left, int mid, int right)
{
int begin1 = left;
int end1 = mid;
int begin2 = mid + 1;
int end2 = right;
int index = left;
while (begin1 <= end1&&begin2 <= end2)
{
if (arr[begin1] < arr[begin2])
{
tmp[index++] = arr[begin1++];
}
else
{
tmp[index++] = arr[begin2++];
}
}
while (begin1 <= end1)
{
tmp[index++] = arr[begin1++];
}
while (begin2 <= end2)
{
tmp[index++] = arr[begin2++];
}
memcpy(arr, tmp, sizeof(int)*index);
}
非递归方式
void Merge_sort(int *a, int length)
{
int i, begin1, end1, begin2, end2, index;
int *tmp = new int[length];
for (i = 1; i < length; i *= 2)
{
for (begin1 = 0; begin1 < length - i; begin1 = end2)
{
begin2 = end1 = begin1 + i;
end2 = end1 + i;
if (end2 > length)
end2 = length;
index = 0;
while (begin1 < end1 && begin2 < end2)
tmp[index++] = a[begin1] > a[begin2] ? a[begin2++] : a[begin1++];
while (begin1 < end1)
a[--begin2] = a[--end1];
while (index > 0)
a[--begin2] = tmp[--index];
}
}
delete []tmp;
}
五、其他
(1)时间复杂度:O(NlogN)
(2)空间复杂度:O(N)
(3)稳定性:稳定