简介
归并排序简言之就是合并两个有序表
对于一个初始状态为无序的序列,我们先将其分割成左右子序列,然后对这两个左右子序列递归应用归并排序,最后依次合并各个有序子序列
那么如何分割呢?简单,2等分即可
那么如何合并这两个有序表呢?
假设有两个有序数组A、B,输出数组C,以及指向这三个数组的索引i、j、k,这三个索引初始值均为数组首元素位置,然后将A、B中较小的那个元素移动到C,更新较小者数组和C数组的索引值,依次类推,直到遍历完A、B所有元素,详见下图:
代码
注意,malloc调用的地方,千万不要在递归内部频繁分配释放内存,因为动态释放这种临时小内存是非常耗时的,因此,一次性分配好即可。
void Merge(int nums[], int tmpNums[], int lstart, int rstart, int rend)
{
int i = 0, lend = rstart - 1, tmpPos = lstart;
const int numSize = rend - lstart + 1;
while ( (lstart <= lend) && (rstart <= rend) ) {
if (nums[lstart] <= nums[rstart]) {
tmpNums[tmpPos++] = nums[lstart++];
}
else {
tmpNums[tmpPos++] = nums[rstart++];
}
}
while (lstart <= lend) {
tmpNums[tmpPos++] = nums[lstart++];
}
while (rstart <= rend) {
tmpNums[tmpPos++] = nums[rstart++];
}
for (i = 0; i < numSize; i++, rend--) {
nums[rend] = tmpNums[rend];
}
}
void Msort(int nums[], int tmpNums[], int left, int right)
{
int center = (left + right) / 2;
if (left < right) {
Msort(nums, tmpNums, left, center);
Msort(nums, tmpNums, center + 1, right);
Merge(nums, tmpNums, left, center + 1, right);
}
}
void Mergersort(int nums[], int N)
{
int * tmpArray = NULL;
tmpArray = (int *)malloc(N * sizeof(int));
if (tmpArray != NULL) {
Msort(nums, tmpArray, 0, N - 1);
free(tmpArray);
}
else {
// 错误处理
}
}
参考文献
数据结构与算法分析第二版