1. 归并操作
归并排序是在归并操作上实现的。先了解一下归并操作的原理。
归并操作:将两个有序数组合并为一个新的有序数组。
如有序数组A=[1, 4, 6], B=[2, 4, 5],将其进行合并。设置变量下标i和j分别表示数组A和B的下标。遍历完数组A和B,最终合并后数组为C。
- 若A[i] <= B[j],则将A[i]保存到数组C,并将i++;
- 若A[i] > B[j],则将B[j]保存到数组C,并将j++;
归并操作的具体实现如下:
void Merge(int *piArrayA, int iArrayALen, int *piArrayB, int iArrayBLen, int *piArrayC)
{
int iIndex1 = 0; /* 指向数组A下标 */
int iIndex2 = 0; /* 指向数组B下标 */
int iIndex3 = 0; /* 指向数组C下标 */
while ((iIndex1 < iArrayALen) || (iIndex2 < iArrayBLen))
{
if ((iIndex1 < iArrayALen)
&& ((iIndex2 >= iArrayBLen) || (piArrayA[iIndex1] < piArrayB[iIndex2]))
{
/* 当数组A还没遍历完时,若数组B已经遍历完或者当前数组A的值小于数组B的值,则将当前数组A的值保存到新数组C */
piArrayC[iIndex3++] = piArrayA[iIndex1];
/* 将数组A下标前移 */
iIndex1++;
}
else
{
/* 其他情况将当前数组B的值保存到新数组C */
piArrayC[iIndex3++] = piArrayB[iIndex2];
/* 将数组B下标前移 */
iIndex2++;
}
}
return;
}
2. 归并排序
归并排序是在归并操作基础上实现的。由于归并操作的前提是数组有序,因此我们可以考虑将待排序数组一分为二,先将一分为二的两个子数组变得有序后,再利用归并操作合并该两个子数组,此时整个数组将变得整体有序。
基于上述思想,我们使用递归操作,持续将数组一分为二,将数组划分得只有一个元素时,其将变得天然有序,此时将其合并,层层操作,最终将实现整个数组排序。
具体代码如下:
/* 归并操作 */
void Merge(int *piArrayA, int iArrayALen, int *piArrayB, int iArrayBLen, int *piArrayC)
{
int iIndex1 = 0; /* 指向数组A下标 */
int iIndex2 = 0; /* 指向数组B下标 */
int iIndex3 = 0; /* 指向数组C下标 */
while ((iIndex1 < iArrayALen) || (iIndex2 < iArrayBLen))
{
if ((iIndex1 < iArrayALen)
&& ((iIndex2 >= iArrayBLen) || (piArrayA[iIndex1] < piArrayB[iIndex2]))
{
/* 当数组A还没遍历完时,若数组B已经遍历完或者当前数组A的值小于数组B的值,则将当前数组A的值保存到新数组C */
piArrayC[iIndex3++] = piArrayA[iIndex1];
/* 将数组A下标前移 */
iIndex1++;
}
else
{
/* 其他情况将当前数组B的值保存到新数组C */
piArrayC[iIndex3++] = piArrayB[iIndex2];
/* 将数组B下标前移 */
iIndex2++;
}
}
return;
}
/* 归并排序 */
/* 递归操作 */
void MergeSort(int *piNums, int iNumsSize)
{
int iMiddle = 0;
int aiLeftArray[iNumsSize];
int aiRightArray[iNumsSize];
if (iNumsSize <= 1)
{
/* 当数组最多只有1个元素时,其天然变得有序,此时结束递归 */
return;
}
iMiddle = iNumsSize / 2;
/* 先将数组一分为二,分别递归 */
/* 左闭右开区间原则 */
/* 对数组左半部分排序 */
memset(aiLeftArray, 0, sizeof(aiLeftArray));
memcpy(aiLeftArray, piNums, sizeof(int) * iMiddle);
MergeSort(aiLeftArray, iMiddle);
/* 对数组右半部分排序 */
memset(aiRightArray, 0, sizeof(aiRightArray));
memcpy(aiRightArray, piNums + iMiddle, sizeof(int) * (iNumsSize - iMiddle));
MergeSort(aiRightArray, iNumsSize - iMiddle);
memset(piNums, 0, sizeof(int) * iNumsSize);
/* 对排好序的左右半部分数组进行归并操作 */
Merge(aiLeftArray, iMiddle, aiRightArray, iNumsSize - iMiddle, piNums);
return;
}
从上可以看出,归并排序利用的是分治思想。