简体   繁体   English

合并排序3方式拆分C

[英]Merge sort 3 way split C

Sorry for annoying anyone here, but I'm having an issue with my merge sort code. 抱歉让这里的任何人烦恼,但是我的合并排序代码有问题。 Previously I could code the 2-way merge sort and when I tried to adapt my merge sort to be an 3-way merge sort my compiler gave me: 9154 segmentation fault(core dumped) . 以前,我可以编写2向合并排序的代码,当我尝试将合并排序调整为3向合并排序时,我的编译器给了我: 9154 segmentation fault(core dumped) Could you help me to fix this? 你能帮我解决这个问题吗? there is my code: 有我的代码:

#include <stdio.h>

void merge(int v[], int p, int q, int r) {
    int i, j, k, b[10];
    for (i = p; i <= q; i++) {
        b[i] = v[i];
    }
    for (j = q + 1; j <= r; j++) {
        b[r + q + 1 - j] = v[j];
    }
    i = p;
    j = r;
    for (k = p; k <= r; k++) {
        if (b[i] <= b[j]) {
            v[k] = b[i];
            i++;
        } else {
            v[k] = b[j];
            j--;
        }
    }
}
void mersort(int v[], int p, int r) { //2-way mergesort that works
    int q;
    if (p < r) {
        q = (p + r) / 2;
        mersort(v, p, q);
        mersort(v, q + 1, r);
        merge(v, p, q, r);
    }
}
void mersort3(int v[], int p, int r) {//not working
    int q, s;
    if (r > p) {
        q = p + (p + r) / 3;
        s = p + 2 * ((p + r) / 3) + 1;
        mersort3(v, p, q);
        mersort3(v, q, s);
        mersort3(v, s, r);
        merge(v, p, q, s);
        merge(v, p, s, r);
    }
}

Your main problems are due to out-of-range indexing due to improper index calculations, and potential infinite recursion for the same reason. 您的主要问题是由于索引计算不正确而导致索引超出范围,以及出于相同原因的潜在无限递归。

You're overcomplicating this tremendously. 您使这个复杂化了很多。 One of the beautiful advantages to C is pointer arithmetic , which makes things like sequence partitioning and traversals like this much, much simpler. C的美丽优点之一是指针算法 ,它使诸如序列划分和遍历这样的事情变得非常简单。 As a bonus, you also get to remove one of your function arguments, as the only reason it is there is the base-adjustment, which is taken care of with the pointer arithmetic. 另外,您还可以删除一个函数参数,这是它存在基址调整的唯一原因,该调整由指针算术解决。

For example, a simple VLA-based merge algorithm (obviously, don't invoke this with a large sequence) 例如,一个简单的基于VLA的合并算法(显然,请勿大序列调用此算法)

/* a simple little VLA-based merge. don't invoke with huge arrays */
void merge(int v[], size_t mid, size_t len)
{
    if (len < 2)
        return;

    size_t i=0, j=mid, k=0;
    int tmp[len];

    while (i < mid && j < len)
        tmp[k++] = (v[i] < v[j]) ? v[i++] : v[j++];

    memcpy(tmp+k, v+i, (mid-i) * sizeof *v);
    memcpy(v, tmp, (k + (mid-i)) * sizeof *v);
}

Well, not a great showcase of pointer arithmetic, but there's some in there. 好吧,这不是一个很好的指针算法展示,但是里面有一些。 The place where it really shines is the partitioning algorithms. 真正发挥作用的地方是分区算法。 For example, a simple merge sort: 例如,一个简单的合并排序:

void mersort(int v[], size_t len)
{
    if (len < 2)
        return;

    size_t mid = len/2;
    mersort(v, mid);
    mersort(v+mid, len-mid); // see here.
    merge(v, mid, len);
}

Extending this to a three-way partitioning scheme becomes: 将其扩展为三向分区方案将成为:

void mersort3(int v[], size_t len)
{
    if (len < 3)
    {
        mersort(v, len);
        return;
    }

    size_t m1 = len/3;
    size_t m2 = (2 * len)/3;
    mersort3(v, m1);
    mersort3(v+m1, m2-m1);   // see here
    mersort3(v+m2, len-m2);  // and here
    merge(v, m1, m2);
    merge(v, m2, len);
}

An example invoke that uses a guaranteed-unusual partition size is below (the sequence is 29 elements long) 下面是使用保证的异常分区大小的示例调用(序列长29个元素)

int main()
{
    srand((unsigned)time(NULL));

    const size_t N = 29;
    size_t i,j;
    int ar[N], n=0;

    // build a sequence from 1..29
    for (i=0; i<N; ++i)
        ar[i] = ++n;

    // shuffle the sequence
    for (i=0; i<3; ++i)
    {
        for (j=0; j<N; ++j)
        {
            n = rand() % N;
            int tmp = ar[n];
            ar[n] = ar[j];
            ar[j] = tmp;
        }
    }

    // show the shuffled sequence
    for (i=0; i<N; ++i)
        printf("%d ", ar[i]);
    fputc('\n', stdout);

    // sort it
    mersort3(ar, N);

    // show it again
    for (i=0; i<N; ++i)
        printf("%d ", ar[i]);
    fputc('\n', stdout);

    return EXIT_SUCCESS;
}

Output (shuffled sequence varies) 输出 (混排顺序不同)

21 8 11 27 18 9 17 28 20 14 15 1 29 6 19 22 7 2 16 23 5 12 4 3 10 26 13 25 24 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM