我的(基于指针)mergesort有什么问题?

时间:2015-08-31 00:55:56

标签: c++ mergesort

没有错误,只是不对列表进行排序。当我直接使用索引而不是指针时,它工作。 我觉得我错过了指针应该表现的方式......假设指针是通过值(复制)传递给递归调用的,或者我是否将它们搞砸了,我是否正确?

#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

3 个答案:

答案 0 :(得分:3)

我认为你的合并有问题。两个子阵列没有边界测试,所以只要你到达一个数组的末尾,你就会从另一个数组中获取值(已经被复制了)。

将合并代码拆分为三个循环是正常的,如下所示:

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++;

答案 1 :(得分:1)

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;
}

答案 2 :(得分:0)

sort1中的基本案例是倒退的;更具体地说,计算n