#include <cstdio>
#include <cstdlib>
#include <cstring>
#define INF 0x7fffffff
//使用哨兵
void merge(int *A, int l, int r) {
if (l >= r) return;
int mid = (l + r) >> 1;
merge(A, l, mid);
merge(A, mid + 1, r);
int n1 = mid - l + 2;
int n2 = r - mid + 1;
int *L = (int*)malloc(sizeof(int) * n1);
int *R = (int*)malloc(sizeof(int) * n2);
L[n1 - 1] = INF; //设置哨兵
R[n2 - 1] = INF;
for (int i = 0; i < n1 - 1; i++) {
L[i] = A[l + i];
}
for (int i = 0; i < n2 - 1; i++) {
R[i] = A[mid + i + 1];
}
int n = r - l + 1, i = 0, j = 0;
for (int k = l; k <= r; k++) {
if (L[i] < R[j]) A[k] = L[i++];
else A[k] = R[j++];
}
free(L);
free(R);
}
//不使用哨兵
void merge2(int* A, int l, int r) {
if (l >= r) return;
int mid = (l + r) >> 1;
merge2(A, l, mid);
merge2(A, mid + 1, r);
int n = r - l + 1;
int* temp = (int*)malloc(sizeof(int) * n);
int ind1 = l, ind2 = mid + 1;
for (int i = 0; i < n; i++) {
//复杂的边界判断
if (ind1 <= mid && (A[ind1] < A[ind2] || ind2 > r)) temp[i] = A[ind1++];
else temp[i] = A[ind2++];
}
memcpy(A + l, temp, n * sizeof(int));
free(temp);
}
int main() {
int A[8] = {3, 41, 52, 26, 38, 57, 9, 49};
merge2(A, 0, 7);
for (int i = 0; i < 8; i++) {
printf("%d ", A[i]);
}
printf("\n");
return 0;
}
使用哨兵的归并显然更加方便,不用进行复杂的边界判断和处理。
这就像AVLTree中增加虚拟叶子节点一样,通过这种方式往往能够把复杂程序大大简化