我的(基于指针的)合并排序有什么问题?

What's wrong with my (pointer based) mergesort?

本文关键字:排序 什么 问题 合并 于指针 指针 我的      更新时间:2023-10-16

没有错误,只是不排序列表。当我直接使用索引而不是指针时,它可以工作。我觉得我错过了一些关于指针的行为方式... .我假设指针按值传递(复制)到递归调用是正确的吗,还是我把它们弄乱了?

#include<iostream>
using namespace std;
void merge(int *start, int *pivot, int *end) {
    const int n = start - end;
    int ret[n];
    int i;
    for (i=0; i<n; ++i) {
        if (*start < *pivot) {
            ret[i] = *(start++);
        }
        else {
            ret[i] = *(pivot++);
        }
    }
    for (i=0;i<n;++i) {
        start[i] = ret[i];
    }
}
void sort1(int* start,int* end) {
    int n = end - start;
    if (n <= 1) {
        return;
    }
    int* pivot = &start[n/2];
    sort1(start,pivot);
    sort1(pivot,end);
    merge(start,pivot,end);
}
int main() {
    int x[] = {1,3,6,2,4,5};
    sort1(x,x+6);
    int i;
    for (i=0; i<6; ++i) {
        cout << x[i] << endl;
    }
}

当前输出是1 1 3 3 1 1

我认为你的合并是错误的。在两个子数组上没有边界测试,所以只要到达一个数组的末尾,就会从另一个数组(已经复制的)中获取值。

通常将合并代码分成三个循环,如下所示:

int *a1 = start;
int *a2 = pivot;
int *r = &ret[0];
// Copy smallest from each sub-array
while( a1 != pivot && a2 != end ) {
    if( *a1 < *a2 ) *r++ = *a1++;
    else *r++ = *a2++;
}
// Copy remaining values from first sub-array
while( a1 != pivot ) *r++ = *a1++;
// Copy remaining values from second sub-array
while( a2 != end ) *r++ = *a2++;

merge()重用start和middle,一些代码推进两个指针,而其他代码期望它们是原始值。n应该是end-start(而不是start-end)。注意-使用ret[]的堆栈将是一个大数组的问题。New和delete可以用来代替_alloca,或者在main中分配并作为参数传递的第二个数组。清理后的示例:

#include <iostream>
// using _alloca since VS doesn't support variable length array
#include <malloc.h>
using namespace std;
void merge(int *start, int *middle, int *end) {
    const int n = (int)(end - start);
    int *ret   = (int *) _alloca(n * sizeof(int));
    int *left  = start;
    int *right = middle;
    int i;
    for (i=0; i < n; ++i) {
        if (right >= end || left < middle && *left <= *right) {
            ret[i] = *(left++);
        } else {
            ret[i] = *(right++);
        }
    }
    for (i=0;i<n;++i) {
        start[i] = ret[i];
    }
}
void sort1(int* start, int* end) {
    int n = (int)(end - start);
    if (n <= 1) {
        return;
    }
    int* middle = &start[n/2];
    sort1(start,middle);
    sort1(middle,end);
    merge(start,middle,end);
}
int main() {
    int x[] = {1,3,6,2,4,5};
    sort1(x,x+6);
    int i;
    for (i=0; i<6; ++i) {
        cout << x[i] << endl;
    }
    return 0;
}

您在sort1中的基本情况是向后的;具体来说,n的计算