优化的归并排序:设定一个阈值(THRESHOLD),对大于该阀值的区间进行归并排序,反之用插入排序。在合并两个已拍好的区间时,通过倒置后面一个区间,比较两个下标来判断拷贝结束。
/****************** 优化的归并排序 ******************/
const int THRESHOLD = 28;
template <class Record>
void InsertSort (Record Array[], int n)
{
// 直接插入排序,Array[]为待排序数组,n为数组长度
Record TempRecord; // 临时变量
for (int i=1; i<n; i++) // 依次插入第i个记录
{
TempRecord=Array[i];
int j = i-1;
//从i开始往前寻找记录i的正确位置
while (j >= 0 && TempRecord < Array[j])
{
Array[j+1] = Array[j]; // 将那些大于等于记录i的记录后移
j = j - 1;
}
Array[j+1] = TempRecord; // 此时j后面就是记录i的正确位置,回填
}
}
template <class Record>
void ModMerge(Record Array[],Record TempArray[],int left,int right,int middle) //归并过程
{
int index1,index2; // 两个子序列的起始位置
int i,j,k ;
for (i=left; i<=middle; i++) // 复制左边的子序列
TempArray[i] = Array[i];
for (j=1; j<=right-middle; j++) // 复制右边的子序列,但顺序颠倒过来
TempArray[right-j+1] = Array[j+middle];
// 开始归并,取较小者插入合并数组中
for (index1=left, index2=right, k=left; k<=right; k++)
if (TempArray[index1] <= TempArray[index2]) // 为保证稳定性,相等时左边优先
Array[k] = TempArray[index1++];
else Array[k] = TempArray[index2--];
}
template <class Record>
void ModMergeSort(Record Array[], Record TempArray[], int left, int right)
{
// if (right <= left) return; // 如果只含有一个元素,直接返回
if (right-left+1 > THRESHOLD) //如果序列长度大于阈值(16最佳),跳出递归
{
int middle=(left+right)/2; // 从中间划分为两个子序列
ModMergeSort(Array, TempArray ,left,middle); // 对左边一半进行递归
ModMergeSort(Array, TempArray ,middle+1,right); // 对右边一半进行递归
ModMerge(Array, TempArray ,left,right,middle); // 进行归并
}
else InsertSort(&Array[left],right-left+1); // 若长度小于等于阈值,采用直接插入排序
}
template <class Record>
void sort(Record* array, int n)
{
static Record* temp = NULL;
if (temp == NULL) temp = new Record[n]; // 申请辅助数组
ModMergeSort(array, temp, 0, n-1);
}