归并排序是一种基于分治法的一种排序方法。它将要排序的序列分成两个长度相等的子序列,为每一个子序列进行排序,然后再将子序列合并成一个有序的序列。
实现:
void _MergeSort(int *a,int begin,int end,int *tmp)
{
int mid = ((begin^end) >> 1) + (begin&end);
if (mid > begin)
_MergeSort(a,begin,mid,tmp);
if (mid + 1 < end)
_MergeSort(a,mid+1,end,tmp);
int begin1 = begin;
int end1 = mid;
int begin2 = mid + 1;
int end2 = end;
int index = begin;
while(begin1<=end1&&begin2<=end2) //先将归并时的元素放到辅助数组中,如果放到原数组的话有可能会覆盖掉其他元素产生错误
{
if (a[begin1] < a[begin2])
{
tmp[index++] = a[begin1++];
}
else
{
tmp[index++] = a[begin2++];
}
}
while(begin1 <= end1)
{
tmp[index++] = a[begin1++];
}
while (begin2 <= end2)
{
tmp[index++] = a[begin2++];
}
while (begin <= end) //将辅助数组中的元素再拷贝到原数组中
{
a[begin] = tmp[begin++];
}
}
void MergeSort(int *a,int begin,int end)
{
assert(a);
int *tmp = new int[end-begin+1];
_MergeSort(a,begin,end,tmp);
delete[] tmp;
}
优化:
当划分的子区间的元素小于13个元素左右时,再使用归并的话会效率不会很高,相当于多增加了二叉树的后面几层的结点。这时候我们改用直接插入排序来进行优化。
void _MergeSort(int *a,int begin,int end,int* tmp)
{
int mid = ((begin^end) >> 1) + (begin&end);
if (begin<mid)
{
if (mid - begin>13)
{
_MergeSort(a, begin, mid, tmp);
}
else
{
InsertSort(a+begin, end - begin + 1);
}
}
if (mid + 1 < end)
{
if (end - mid - 1 > 13)
{
_MergeSort(a,mid+1,end,tmp);
}
else
{
InsertSort(a+mid+1,end-mid);
}
}
int begin1 = begin;
int end1 = mid;
int begin2 = mid + 1;
int end2 = end;
int index = begin;
while (begin1 <= end1&&begin2 <= end2)
{
if (a[begin1] < a[begin2])
tmp[index++] = a[begin1++];
else
tmp[index++] = a[begin2++];
}
while (begin1 <= end1)
tmp[index++] = a[begin1++];
while (begin2 <=end2)
tmp[index++] = a[begin2++];
while(begin<=end)
{
a[begin] = tmp[begin++];
}
}
void MergeSort(int* a,int begin,int end)
{
assert(a);
int *tmp = new int[end-begin+1];
_MergeSort(a,begin,end,tmp);
delete[] tmp;
}