void merge(int A[], int p, int q, int r) {
int *tmpL, *tmpR;
int boundary;
int n1, n2;
int i, j, k;
n1 = q - p + 1;
n2 = r - q;
tmpL = (int *)malloc(sizeof(int) * (n1 + 1));
tmpR = (int *)malloc(sizeof(int) * (n2 + 1));
for (i = 0; i < n1; i++)
tmpL[i] = A[p + i];
for (j = 0; j < n2; j++)
tmpR[j] = A[q + j + 1];
boundary = tmpL[n1 - 1] > tmpR[n2 - 1] ? tmpL[n1 - 1] + 1 : tmpR[n2 - 1] + 1;
tmpL[n1] = boundary;
tmpR[n2] = boundary;
i = 0;
j = 0;
for (k = p; k <= r; k++) {
if (tmpL[i] <= tmpR[j]) {
A[k] = tmpL[i];
i++;
} else {
A[k] = tmpR[j];
j++;
}
}
free(tmpL);
free(tmpR);
}
void merge_sort(int A[], int p, int r) {
int q;
if (p < r) {
q = (p + r) / 2;
merge_sort(A, p, q);
merge_sort(A, q + 1, r);
merge(A, p, q, r);
}
}
我无法完全理解这个无限边界代码 boundary = tmpL[n1 - 1] > tmpR[n2 - 1] ? tmpL[n1 - 1] + 1 : tmpR[n2 - 1] + 1;
谢谢https://i.stack.imgur.com/UmyUg.png(蓝色圆圈)
这是一个条件语句,A> B? C:D
。如果A> B
为true,则评估C,否则评估D。但是我仍然不了解边界部分。这与添加两个while循环来处理时(其中一半有剩余元素并将它们附加到新数组的末尾)一样吗?
如果我不将它们初始化为无限边界,它们可能会给我带来分割错误。
该代码使用一种通用方法来mergesort
复制两个子数组的副本,并在末尾添加一个额外的元素,其值设置为大于两个数组的最大值。
该语句boundary = tmpL[n1 - 1] > tmpR[n2 - 1] ? tmpL[n1 - 1] + 1 : tmpR[n2 - 1] + 1;
尝试将值计算boundary
为1加上最大值tmpL
或tmpR
取决于哪个更大。它使用三元表达式,大致相当于编写:
if (tmpL[n1 - 1] > tmpR[n2 - 1])
boundary = tmpL[n1 - 1] + 1;
else
boundary = tmpR[n2 - 1] + 1;
然后合并循环可以使用一个单一的测试k <= r
结束循环和i
将等于n1
和j
将等于n2
当k
达到r + 1
。
这种方法在很多方面都被打破了:
INT_MAX
,的计算boundary
将溢出并导致未定义的行为。即使溢出不会引起致命的副作用,的值boundary
也将毫无意义,从而导致错误的结果或其他未定义的行为。merge
不会覆盖尚未复制的值。我认为,完全不应教授这种方法。
这是没有这些缺点的替代实现:
void merge(int A[], int p, int q, int r) {
int *tmpL;
int n1, n2;
int i, j, k;
// It is much simpler to consider q to point to the first element of
// the second subarray and r to point after the last element of that array.
q++;
r++;
n1 = q - p; // number of elements in the left sorted subarray
n2 = r - q; // number of elements in the right sorted subarray
tmpL = (int *)malloc(sizeof(int) * n1);
if (tmpL == NULL) {
// Report this fatal error or fall back to a different
// algorithm that does not require allocation, such as
// heapsort or insertion sort.
return;
}
// Make a copy of the left subarray as elements may be overwritten in the loop.
for (i = 0; i < n1; i++) {
tmpL[i] = A[p + i];
}
// Merge the elements of the subarrays:
// - if all elements of the left array have been merged,
// the remaining elements of the right subarray are already in place
// - if k has reached r, all elements have been sorted
for (i = j = 0, k = p; i < n1 && k < r; k++) {
if (j >= n2 || tmpL[i] <= A[q + j]) {
// Take the element from tmpL if the right subarray is empty
// or if it is no greater than the next one from the right subarray.
A[k] = tmpL[i];
i++;
} else {
// Otherwise take the element from the right subarray.
A[k] = a[q + j];
j++;
}
}
free(tmpL);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句