基础算法改进——归并排序的改进
基础算法改进——归并排序的改进
简介:
改进方案:
1.小区间采用插入排序(原因:小区间内元素有序的概率较大,)
2.待比较两区间元素间已经有序,直接返回(区间内部肯定是已经有的,这是归并的原理)
** 2.1** 正序:前子序列的最大值<=后子序列的最小值,直接返回
** 2.2** 逆序:后子序列的最大值<=前子序列的最小值,先复制后子序列,再复制前子序列。
3.临时数组的有效利用
4:不递归:
** 4.1**:用栈模拟递归,即用自定义的栈来模拟系统栈的递归过程从而避免递归
** 4.2**:递推,即把通常的归并过程反过来实现,自下而上不断合并,首先定义一个长度初始为1,然后不断以这个长度为单位分割数组并两两合并,一轮结束以后长度乘以二,不断重复上述过程直至该长度大于数组实际长度。
5:原地归并(空间复杂度为O(1))
改进前代码:
//CC_MergeSort.cpp
int* Tmp = new int[1000000];
template<class T>
void CC_MergeSort(T* begin,int Len)//归并排序
{
if (!Len) return;
T* A = begin;
int mid = Len / 2, i = 0, j = mid + 1, k = 0;
CC_MergeSort(&A[0], mid);
CC_MergeSort(&A[mid + 1], Len - mid - 1);
while (i <= mid && j <= Len)
if (A[i] <= A[j])
Tmp[k++] = A[i++];
else
Tmp[k++] = A[j++];
while (i <= mid)
Tmp[k++] = A[i++];
while (j <= Len)
Tmp[k++] = A[j++];
for (int l = 0; l <= Len; l++)
A[l] = Tmp[l];
}
利用方案一改进:
void CC_InsertSort(T* begin, int Len)
{
T t,* A = begin;
int i,j;
for (i = 1; i <= Len; i++)
if (A[i] < A[i - 1]) {
t = A[i];
for (j = i - 1; j >= 0 && A[j] > t; j--)
A[j + 1] = A[j];
A[j+1] = t;
}
}
//在Merge内:
if (Len < 15) { //小区间采用插入排序
CC_InsertSort(A, Len);
return;
}
利用方案二改进:
if (A[mid] < A[mid + 1])//前子序列的最大值<=后子序列的最小值,直接返回
return;
if (A[Len] < A[0]) {//后子序列的最大值<=前子序列的最小值,先复制后子序列,再复制前子序列。
while (j <= Len)
Tmp[k++] = A[j++];
while (i <= mid)
Tmp[k++] = A[i++];
for (int l = 0; l <= Len; l++)
A[l] = Tmp[l];
return;
}
前两个方案修改后整体的代码:
#include <iostream>
#include <time.h>
int* Tmp = new int[1000000];
template<class T>//插入排序
void CC_InsertSort(T* begin, int Len)
{
T t,* A = begin;
int i,j;
for (i = 1; i <= Len; i++)
if (A[i] < A[i - 1]) {
t = A[i];
for (j = i - 1; j >= 0 && A[j] > t; j--)
A[j + 1] = A[j];
A[j+1] = t;
}
}
template<class T>
void CC_MergeSort(T* begin,int Len)//归并排序
{
if (!Len) return;
T* A = begin;
int mid = Len / 2, i = 0, j = mid + 1, k = 0;
CC_MergeSort(&A[0], mid);
CC_MergeSort(&A[mid + 1], Len - mid - 1);
if (Len < 15) { //小区间采用插入排序
CC_InsertSort(A, Len);
return;
}
while (i <= mid && j <= Len) {
if (A[mid] < A[mid + 1])//前子序列的最大值<=后子序列的最小值,直接返回
return;
if (A[Len] < A[0]) {//后子序列的最大值<=前子序列的最小值,先复制后子序列,再复制前子序列。
while (j <= Len)
Tmp[k++] = A[j++];
while (i <= mid)
Tmp[k++] = A[i++];
for (int l = 0; l <= Len; l++)
A[l] = Tmp[l];
return;
}
if (A[i] <= A[j])
Tmp[k++] = A[i++];
else
Tmp[k++] = A[j++];
}
while (i <= mid)
Tmp[k++] = A[i++];
while (j <= Len)
Tmp[k++] = A[j++];
for (int l = 0; l <= Len; l++)
A[l] = Tmp[l];
}