【问题标题】:Getting a "Segmentation fault: 11" when finding number of inversions using mergesort in C++在 C++ 中使用合并排序查找反转数时出现“分段错误:11”
【发布时间】:2019-05-09 02:05:21
【问题描述】:

我正在编写一个 C++ 程序,它使用归并排序来查找向量中的反转数。当i'th 元素大于j'th 元素时会发生反转,其中i < j。例如,假设向量是{ 1, 3, 5, 2 },那么有2个反转:{3,2}{5,2}countNsort 函数不断递归和分割向量,直到子向量的长度只有一个元素。 countNsortSplit 函数执行归并排序来排序和计数倒置的次数。

我试过了:

  1. 初始化输入向量的不同方法。 vector<int> a{2,1};vector<int> a; a={2,1};vector<int> a(2); a={2,1};
  2. 将输入向量拆分为子向量的不同方法。 vector<int> c(a.begin()+half, a.begin()+n);vector<int> c(a.begin()+half, a.end());,其中 n 是向量的大小。
  3. 不同的 IDE。 Atoms 给了我这个:bash: line 1: 13763 Segmentation fault: 11 /tmp/cpp.out [Finished in 20.57s],CodeBlocks 给了我这个:error: expected expression 这条线:a={2,1}:
#include <stdio.h>
#include <vector>
#include <iostream>

using namespace std;

struct returnVal {
    int count;
    vector<int> sorted_array;
};

returnVal countNsortSplit(vector<int> left, vector<int> right, int n) {
    returnVal output;
    int count = 0;
    vector<int> merge;
    int i = 0;
    int j = 0;
    for (int k = 0; k < n; k++) {
        if (left[i] < right[j]) {
            merge[k] = left[i];
            i++;
        } else {
            merge[k] = right[j];
            j++;
            // increment count by the # of remaining elements in left
            count += left.size()-i;
        }
    }
    output.sorted_array = merge;
    output.count = count;
    return output;
}

returnVal countNsort(vector<int> a, int n) {
    returnVal output;
    if (n == 1) {
        output.sorted_array = a;
        output.count = 0;
        return output;
    } else {
        returnVal left;
        returnVal right;
        returnVal split;
        int half = n / 2;
        vector<int> b(a.begin(), a.begin() + half);
        vector<int> c(a.begin() + half, a.begin() + n);
        left = countNsort(b, half);
        right = countNsort(c, n - half); // need n-n/2 in case of odd length
        split = countNsortSplit(left.sorted_array, right.sorted_array, n);
        output.sorted_array = split.sorted_array;
        output.count = left.count + right.count + split.count;
        return output;
    }
}

int main() {
    vector<int> a(2);
    //a = {1,3,5,2};
    //a = {1,3,5,2,4,6};
    a = {2, 1};
    returnVal result;
    result = countNsort(a, a.size());
    cout << result.count << endl;
}

【问题讨论】:

  • 附加信息:当第 i 个元素大于第 j 个元素时发生反转,其中 i
  • 您在这里调用 undefined behavior merge[k] 您必须先调整向量的大小,然后才能使用索引运算符访问它。也不要在 cmets 中添加其他信息。你可以随时edit你的问题。
  • 提示:std::vector 在初始化时大小为零。添加元素:push_backemplace_back。对于固定大小:std::array.
  • 推荐使用 asan 或 valgrind 运行此类程序。他们有时会在段错误实际出现之前更早地发现问题。 YMMV

标签: c++ mergesort inversion


【解决方案1】:

你的代码有多个问题:

  • 您没有以适当的大小定义目标向量
  • 您不测试ij 是否分别达到leftright 向量的大小。
  • main() 中向量 a 的初始值设定项的语法无效。

请注意,您不需要将向量大小传递给countNsortcountNsortSplit

这是一个更正的版本:

#include <iostream>
#include <vector>

using namespace std;

struct returnVal {
    int count;
    vector<int> sorted_array;
};

returnVal countNsortMerge(vector<int> left, vector<int> right) {
    int leftSize = left.size();
    int rightSize = right.size();
    int n = leftSize + rightSize;
    int count = 0;
    vector<int> merge(n);
    int i = 0;
    int j = 0;
    for (int k = 0; k < n; k++) {
        if (i < leftSize && (j == rightSize || left[i] < right[j])) {
            merge[k] = left[i++];
        } else {
            merge[k] = right[j++];
            // increment count by the # of remaining elements in left
            count += leftSize - i;
        }
    }
    returnVal output;
    output.sorted_array = merge;
    output.count = count;
    return output;
}

returnVal countNsort(vector<int> a) {
    int n = a.size();
    if (n <= 1) {
        returnVal output;
        output.sorted_array = a;
        output.count = 0;
        return output;
    } else {
        int half = n / 2;
        vector<int> b(a.begin(), a.begin() + half);
        vector<int> c(a.begin() + half, a.begin() + n);
        returnVal left = countNsort(b);
        returnVal right = countNsort(c);
        returnVal result = countNsortMerge(left.sorted_array, right.sorted_array);
        result.count += left.count + right.count;
        return result;
    }
}

int main() {
    //int values[] = { 1, 3, 5, 2 };
    //int values[] = { 2, 1 };
    int values[] = { 1, 3, 5, 2, 4, 6 };
    vector<int> a(values, values + sizeof values / sizeof *values);
    returnVal result = countNsort(a);
    cout << result.count << endl;
    return 0;
}

但是请注意,对向量进行适当的排序并返回反转计数会更有效和惯用:

#include <iostream>
#include <vector>

size_t countNsortMerge(std::vector<int>& a, size_t start, size_t middle, size_t end) {
    std::vector<int> temp(a.begin() + start, a.begin() + middle);
    size_t i = 0;
    size_t leftSize = middle - start;
    size_t j = middle;
    size_t count = 0;
    for (size_t k = start; k < end; k++) {
        if (i < leftSize && (j == end || temp[i] < a[j])) {
            a[k] = temp[i++];
        } else {
            a[k] = a[j++];
            // increment count by the # of remaining elements in left
            count += leftSize - i;
        }
    }
    return count;
}

size_t countNsort(std::vector<int>& a, size_t start, size_t end) {
    if (end - start <= 1) {
        return 0;
    } else {
        size_t middle = start + (end - start) / 2;
        size_t leftCount = countNsort(a, start, middle);
        size_t rightCount = countNsort(a, middle, end);
        return leftCount + rightCount + countNsortMerge(a, start, middle, end);
    }
}

int main() {
    //int values[] = { 1, 3, 5, 2 };
    //int values[] = { 2, 1 };
    int values[] = { 1, 3, 5, 2, 4, 6 };
    std::vector<int> a(values, values + sizeof values / sizeof *values);
    size_t result = countNsort(a, 0, a.size());
    std::cout << result << std::endl;
    return 0;
}

【讨论】:

    猜你喜欢
    • 2017-12-30
    • 2022-01-14
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-15
    相关资源
    最近更新 更多