用递归实现C语言中的合并排序
这是我用C语言编写的合并排序代码。我不明白这里有什么问题。我对指针的了解不多。merge函数接收2个数组并合并它们。sort函数是一个递归函数,用于对数组进行排序用递归实现C语言中的合并排序,c,sorting,recursion,mergesort,C,Sorting,Recursion,Mergesort,这是我用C语言编写的合并排序代码。我不明白这里有什么问题。我对指针的了解不多。merge函数接收2个数组并合并它们。sort函数是一个递归函数,用于对数组进行排序 int * merge(int *fir, int n, int *sec, int m){ int res[m+n]; int x=0, y=0; for(int i = 0; i < m+n; i++){ if(*(fir+x)<=*(sec+y)){
int * merge(int *fir, int n, int *sec, int m){
int res[m+n];
int x=0, y=0;
for(int i = 0; i < m+n; i++){
if(*(fir+x)<=*(sec+y)){
res[i] = *(fir+x);
x++;
}else{
res[i] = *(sec+y);
y++;
}
}
return res;
}
int * sort(int A[], int n){
if(n == 1){
return A;
}
int mid = n/2;
int AL[mid], AR[n-mid];
for(int i = 0; i < mid; i++){
AL[i] = A[i];
}
for(int i = 0; i < n-mid; i++){
AR[i] = A[i+mid];
}
int *BL, *BR;
BL = sort(AL, mid);
BR = sort(AR, n-mid);
return(merge(BL, mid, BR, n-mid));
}
int main(){
int n;
scanf("%d", &n);
int A[n];
for(int i = 0; i < n; i++){
scanf("%d", &A[i]);
}
int *sortedArray;
sortedArray = sort(A, n);
for(int i = 0; i < n; i++){
printf("%d ", *(sortedArray+i));
}
return 0;
}
这里有两个问题:首先,您将部分数组合并到一个临时本地数组中,在您从
merge
返回后,该数组将超出范围。返回的指针指向invlid内存。这就是警告的内容
其次,在合并时,您不检查您的读取是否超出了部分数组的限制:当您访问fir
时,条件x
必须为真,同样对于y
和sec
返回指向已排序或合并数组的第一个元素的指针也会造成混乱。这建议您创建新的排序和合并数组(这就是您在merge
中尝试执行的操作)。这对于垃圾收集的morern语言来说是可以的,但是C不是这样工作的
在C语言中,如果您需要新的内存,您必须分配它,然后显式地释放它。在像您这样的递归函数中,这很乏味,因为您只关心最终排序的数组,而不关心中间结果。因此,C排序算法通常“就地”工作:在排序和元素交换时使用相同的内存。元素的原始顺序将丢失,除非在排序之前复制
对于合并排序,您需要辅助内存。在本例中,您使用临时数组AL
和AR
,它们是原始数组A
内容的副本。现在,当您合并时,您可以将AL
和AR
合并回A
因此,在创建临时本地数组之前,传入a
,以便可以用已排序的元素填充该数组:
void sort(int A[], int n)
{
if (n > 1) {
int mid = n / 2;
int AL[mid], AR[n - mid];
for (int i = 0; i < mid; i++) AL[i] = A[i];
for (int i = 0; i < n - mid; i++) AR[i] = A[i + mid];
sort(AL, mid);
sort(AR, n - mid);
merge(A, AL, mid, AR, n - mid);
}
}
您正在读取超出数组边界的内容。合并阵列时,有四种情况。您的代码忽略了两种情况:一个数组耗尽,而您从另一个数组中获取第一项。此外,还存在返回本地数组地址的问题<代码>分辨率。从
merge
返回后,该数组将不再有效,指向该数组的指针将为“stale”。(这就是警告的内容。)对于*(fir+x)
你可以只写fir[x]
,这样更容易阅读。是的,我理解我的两个错误。非常感谢您指出这些问题!对我明白我做错了什么。非常感谢你帮了我的忙!
void sort(int A[], int n)
{
if (n > 1) {
int mid = n / 2;
int AL[mid], AR[n - mid];
for (int i = 0; i < mid; i++) AL[i] = A[i];
for (int i = 0; i < n - mid; i++) AR[i] = A[i + mid];
sort(AL, mid);
sort(AR, n - mid);
merge(A, AL, mid, AR, n - mid);
}
}
void merge(int *res, const int *fir, int n, const int *sec, int m)
{
int x = 0, y = 0;
for(int i = 0; i < m + n; i++) {
if (x == n) res[i] = sec[y++];
else if (y == m) res[i] = fir[x++];
else if (fir[x] <= sec[y]) res[i] = fir[x++];
else res[i] = sec[y++];
}
}