C 中的合并排序代码无法正常工作
Code in Merge Sort in C not working properly
int lb = 0, ub = 8, mid; //ub=upper bound,lb=lower bound.
int i = 0, j = 0, k = 0;
int a[] = { 15, 5, 24, 8, 1, 3, 16, 10, 20 };
int b[10];
void mergeSort(int a[], int lb, int ub) {
if (lb < ub) {
mid = ((lb + ub) / 2);
mergeSort(a, lb, mid);
mergeSort(a, mid + 1, ub);
merge(a, lb, mid, ub);
}
}
void merge(int a[], int lb, int mid, int ub) {
i = lb;
j = mid + 1;
k = lb;
while (i <= mid && j <= ub) {
if (a[i] <= a[j]) {
b[k] = a[i];
i++;
} else {
b[k] = a[j];
j++;
}
k++;
}
if (i > mid) {
while (j <= ub) {
b[k] = a[j];
j++;
k++;
}
} else {
while (i <= mid) {
b[k] = a[i];
i++;
k++;
}
}
for (k = lb; k <= ub; k++) {
a[k] = b[k];
}
}
void printList(int A[]) {
for (k = 0; k <= 8; k++) {
printf("%d\n", A[k]);
}
printf("done\n");
}
int main() {
printList(a);
mergeSort(a, 0, 8);
printList(a);
}
我觉得mergesort
和merge
的代码不是问题,问题是我怎么检查了很多次代码都找不到错误,所以我希望有人能解释一下请问我哪里出了问题,谢谢大家帮忙!!
我运行代码时的输出:
5
15
8
1
3
16
10
20
24
done
这不是排序列表。
问题是 mid
是一个全局变量,因此它被递归调用 mergeSort(a, lb, mid);
修改,并且另一个值用于第二次递归调用 mergeSort(a, mid + 1, ub);
但是最终调用使用了不同的值 merge(a, lb, mid, ub);
产生了意外结果,并可能导致未定义的行为。
不要使用全局变量。在 main
中定义两个数组,在 merge
和 mergeSort
中创建 i
、j
、k
和 mid
局部变量并传递辅助数组 b
到 merge
和 mergeSort
.
这是修改后的版本:
#include <stdio.h>
void merge(int a[], int lb, int mid, int ub, int b[]) {
int i = lb;
int j = mid + 1;
int k = lb;
while (i <= mid && j <= ub) {
if (a[i] <= a[j]) {
b[k] = a[i];
i++;
} else {
b[k] = a[j];
j++;
}
k++;
}
if (i > mid) {
while (j <= ub) {
b[k] = a[j];
j++;
k++;
}
} else {
while (i <= mid) {
b[k] = a[i];
i++;
k++;
}
}
for (k = lb; k <= ub; k++) {
a[k] = b[k];
}
}
void mergeSort(int a[], int lb, int ub, int b[]) {
if (lb < ub) {
int mid = (lb + ub) / 2;
mergeSort(a, lb, mid, b);
mergeSort(a, mid + 1, ub, b);
merge(a, lb, mid, ub, b);
}
}
void printList(int A[], int len) {
for (int k = 0; k < len; k++) {
printf(" %d", A[k]);
}
printf("\n");
}
int main() {
int a[] = { 15, 5, 24, 8, 1, 3, 16, 10, 20 };
int len = sizeof(a) / sizeof(a[0]);
// make b a temporary array the same size as a
int b[len];
printf("before:");
printList(a, len);
mergeSort(a, 0, len - 1, b);
printf("after:");
printList(a, len);
return 0;
}
输出:
before: 15 5 24 8 1 3 16 10 20
after: 1 3 5 8 10 15 16 20 24
请注意,将 ub
作为最后一个切片之后的元素的索引传递是不是更不容易出错,这样切片长度为 ub - lb
并且您不需要任何令人困惑的 +1
/-1
调整。此外,不需要从右半部分复制剩余的元素,因为它们已经在目标数组中的正确位置。
这是经过简化的修改版本:
#include <stdio.h>
void merge(int a[], int lb, int mid, int ub, int b[]) {
int i = lb;
int j = mid;
int k = lb;
while (i < mid && j < ub) {
if (a[i] <= a[j]) {
b[k++] = a[i++];
} else {
b[k++] = a[j++];
}
}
while (i < mid) {
b[k++] = a[i++];
}
for (i = lb; i < k; i++) {
a[i] = b[i];
}
}
void mergeSort(int a[], int lb, int ub, int b[]) {
if (ub - lb >= 2) {
int mid = lb + (ub - lb) / 2;
mergeSort(a, lb, mid, b);
mergeSort(a, mid, ub, b);
merge(a, lb, mid, ub, b);
}
}
void printList(int A[], int len) {
for (int k = 0; k < len; k++) {
printf(" %d", A[k]);
}
printf("\n");
}
int main() {
int a[] = { 15, 5, 24, 8, 1, 3, 16, 10, 20 };
int len = sizeof(a) / sizeof(a[0]);
// make b a temporary array the same size as a
int b[len];
printf("before:");
printList(a, len);
mergeSort(a, 0, len, b);
printf("after:");
printList(a, len);
return 0;
}
int lb = 0, ub = 8, mid; //ub=upper bound,lb=lower bound.
int i = 0, j = 0, k = 0;
int a[] = { 15, 5, 24, 8, 1, 3, 16, 10, 20 };
int b[10];
void mergeSort(int a[], int lb, int ub) {
if (lb < ub) {
mid = ((lb + ub) / 2);
mergeSort(a, lb, mid);
mergeSort(a, mid + 1, ub);
merge(a, lb, mid, ub);
}
}
void merge(int a[], int lb, int mid, int ub) {
i = lb;
j = mid + 1;
k = lb;
while (i <= mid && j <= ub) {
if (a[i] <= a[j]) {
b[k] = a[i];
i++;
} else {
b[k] = a[j];
j++;
}
k++;
}
if (i > mid) {
while (j <= ub) {
b[k] = a[j];
j++;
k++;
}
} else {
while (i <= mid) {
b[k] = a[i];
i++;
k++;
}
}
for (k = lb; k <= ub; k++) {
a[k] = b[k];
}
}
void printList(int A[]) {
for (k = 0; k <= 8; k++) {
printf("%d\n", A[k]);
}
printf("done\n");
}
int main() {
printList(a);
mergeSort(a, 0, 8);
printList(a);
}
我觉得mergesort
和merge
的代码不是问题,问题是我怎么检查了很多次代码都找不到错误,所以我希望有人能解释一下请问我哪里出了问题,谢谢大家帮忙!!
我运行代码时的输出:
5 15 8 1 3 16 10 20 24 done
这不是排序列表。
问题是 mid
是一个全局变量,因此它被递归调用 mergeSort(a, lb, mid);
修改,并且另一个值用于第二次递归调用 mergeSort(a, mid + 1, ub);
但是最终调用使用了不同的值 merge(a, lb, mid, ub);
产生了意外结果,并可能导致未定义的行为。
不要使用全局变量。在 main
中定义两个数组,在 merge
和 mergeSort
中创建 i
、j
、k
和 mid
局部变量并传递辅助数组 b
到 merge
和 mergeSort
.
这是修改后的版本:
#include <stdio.h>
void merge(int a[], int lb, int mid, int ub, int b[]) {
int i = lb;
int j = mid + 1;
int k = lb;
while (i <= mid && j <= ub) {
if (a[i] <= a[j]) {
b[k] = a[i];
i++;
} else {
b[k] = a[j];
j++;
}
k++;
}
if (i > mid) {
while (j <= ub) {
b[k] = a[j];
j++;
k++;
}
} else {
while (i <= mid) {
b[k] = a[i];
i++;
k++;
}
}
for (k = lb; k <= ub; k++) {
a[k] = b[k];
}
}
void mergeSort(int a[], int lb, int ub, int b[]) {
if (lb < ub) {
int mid = (lb + ub) / 2;
mergeSort(a, lb, mid, b);
mergeSort(a, mid + 1, ub, b);
merge(a, lb, mid, ub, b);
}
}
void printList(int A[], int len) {
for (int k = 0; k < len; k++) {
printf(" %d", A[k]);
}
printf("\n");
}
int main() {
int a[] = { 15, 5, 24, 8, 1, 3, 16, 10, 20 };
int len = sizeof(a) / sizeof(a[0]);
// make b a temporary array the same size as a
int b[len];
printf("before:");
printList(a, len);
mergeSort(a, 0, len - 1, b);
printf("after:");
printList(a, len);
return 0;
}
输出:
before: 15 5 24 8 1 3 16 10 20 after: 1 3 5 8 10 15 16 20 24
请注意,将 ub
作为最后一个切片之后的元素的索引传递是不是更不容易出错,这样切片长度为 ub - lb
并且您不需要任何令人困惑的 +1
/-1
调整。此外,不需要从右半部分复制剩余的元素,因为它们已经在目标数组中的正确位置。
这是经过简化的修改版本:
#include <stdio.h>
void merge(int a[], int lb, int mid, int ub, int b[]) {
int i = lb;
int j = mid;
int k = lb;
while (i < mid && j < ub) {
if (a[i] <= a[j]) {
b[k++] = a[i++];
} else {
b[k++] = a[j++];
}
}
while (i < mid) {
b[k++] = a[i++];
}
for (i = lb; i < k; i++) {
a[i] = b[i];
}
}
void mergeSort(int a[], int lb, int ub, int b[]) {
if (ub - lb >= 2) {
int mid = lb + (ub - lb) / 2;
mergeSort(a, lb, mid, b);
mergeSort(a, mid, ub, b);
merge(a, lb, mid, ub, b);
}
}
void printList(int A[], int len) {
for (int k = 0; k < len; k++) {
printf(" %d", A[k]);
}
printf("\n");
}
int main() {
int a[] = { 15, 5, 24, 8, 1, 3, 16, 10, 20 };
int len = sizeof(a) / sizeof(a[0]);
// make b a temporary array the same size as a
int b[len];
printf("before:");
printList(a, len);
mergeSort(a, 0, len, b);
printf("after:");
printList(a, len);
return 0;
}