归并排序基本思想是基于合并,将两个或两个以上有序表合并成一个新的有序表。合并两个子序列的过程称为两路归并。
【算法思想】
假设初始序列含有n个记录,首先将这n个记录看成n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2(n为奇数时,最后一个蓄力的长度为1)的有序子序列。
在此基础上,在对长度为2的有序子序列进行两两归并,得到若干个长度为4的有序子序列。如此重复,直直的道一个长度为n的有序序列为止。
这种方法称为2-路归并排序。
递归实现的归并排序:
void Merge(int *arr, int *temp, 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])
temp[index++] = arr[begin1++];
else
temp[index++] = arr[begin2++];
}
while (begin1 <= end1)
temp[index++] = arr[begin1++];
while (begin2 <= end2)
temp[index++] = arr[begin2++];
}
void _MergerSort(int *arr, int *temp, int left, int right)
{
if (left < right)
{
int mid = left + ((right - left) >> 1);
_MergerSort(arr, temp,left, mid);
_MergerSort(arr, temp, mid+1,right);
Merge(arr, temp, left, mid, right);
memcpy(arr + left, temp + left, sizeof(arr[0])*(right - left + 1));
}
}
void MergeSort(int *arr, int size)
{
int *temp = new int[size];
_MergerSort(arr, temp, 0, size - 1);
delete[]temp;
}
非递归实现的归并排序:
void MergeSortNor(int *arr, int size)
{
int *temp = new int[size];
int left = 0;
int right = size - 1;
int gap = 1;
while (gap < size)
{
for (int idx = 0; idx < size; idx += gap*2)
{
left = idx;
int mid = left + gap - 1;
int right = mid+gap;
if (mid >= size)
mid = size - 1;
if (right >= size)
right = size - 1;
Merge(arr, temp, left, mid, right);
}
memcpy(arr, temp, size*sizeof(arr[0]));
gap <<= 1;
}
delete[]temp;
}
归并排序的效率是比较高的,设数列长为N,将数列分开成小数列一共要logN步,每步都是一个合并有序数列的过程,时间复杂度可以记为O(N),故一共为O(N*logN)。因为归并排序每次都是在相邻的数据中进行操作,所以归并排序在O(N*logN)的几种排序方法(快速排序,归并排序,希尔排序,堆排序)也是效率比较高的。