SIGABRT(信号 6)在使用分而治之的数组中查找多数元素时出错

Posted

技术标签:

【中文标题】SIGABRT(信号 6)在使用分而治之的数组中查找多数元素时出错【英文标题】:SIGABRT (signal 6) error in finding majority element in array using divide and conquer 【发布时间】:2017-06-16 07:42:28 【问题描述】:

我检查了 SO,发现处理同一个问题陈述的两个问题。但是,它们都没有包含我正在寻找的内容。任务是如果具有 n 个元素的数组包含出现超过 n/2 次的元素,则输出 1,使用 分治策略

我开发了我认为可行的解决方案,因为基本情况是一个子数组,其中一个元素(显然)是子数组中的多数元素。然后我继续比较子数组中的这些多数元素,询问它们最终是否发生超过 n/2 次。

更多详情见https://classes.soe.ucsc.edu/cmps102/Fall01/solutions4.pdf(问题4)

我为这个问题写了两种不同的解决方案,一种使用非常简单的 O(n^2) 算法来检查我的解决方案是否适用于所有情况,另一种尝试实现上面链接中描述的算法。

在 main 内部,我针对明显正确但幼稚的解决方案对我的解决方案进行了压力测试。但是,在运行此程序时,我收到了 SIGABRT(信号 6)错误。我的调试器告诉我检查 malloc,对象可能在被释放后被修改。

现在我无法判断我的解决方案是否正确。我真的不知道分配错误是怎么回事,我对 C++ 比较陌生。

代码如下:

#include <algorithm>
#include <iostream>
#include <vector>

using std::vector;

int get_majority_element(vector<int> &a, int left, int right) 


    int m;
    int majority_left, majority_right;      // majority element in either sub array
    int count_right = 0, count_left = 0;    // count for above
    int leftt, rightt;                      // endpoints

    if (a.size() == 1) 
        return a[0];
    
    else 

        m = (left + right)/2;  // calculate mid point

        vector<int> b_left(m);
        vector<int> b_right(right - m);


        // get left sub array
        for (int i = 0; i < m; i++) 
            b_left[i] = a[i];
        

        // set new endpoints
        leftt = 0;
        rightt = m;

        majority_left = get_majority_element(b_left, leftt, rightt);

        for (int i = 0; i < right - m + 1; i++) 
            b_right[i] = a[m+i];
        

        leftt = m;
        rightt = right - m + 1;

        majority_right = get_majority_element(b_right, leftt, rightt);

        // if there is a majority element, count its frequency

        if (majority_left != -1) 
            for (int i = 0; i < a.size(); i++) 
                if (a[i] == majority_left)
                    count_left++;
            
        

        if (majority_right != -1) 
            for (int i = 0; i < a.size(); i++) 
                if (a[i] == majority_right)
                    count_right++;
            
        


        // if both elements in sub arrays are majority and they're different, there is no majority element
        if (count_left == count_right && majority_left != majority_right) 
            return -1;
        

        // check if either sub array has a majority element that occurs more than n/2 times
        else if (count_right > count_left && count_right > a.size()/2) 
                return majority_right;
        
        else if (count_left > count_right && count_left > a.size()/2)
            return majority_left;
        
    

    return -1;




int get_majority_fast(vector<int> &a, int left, int right)

    std::reverse(a.begin(),a.end());

    int current = 0;
    int count;
    for (int i = 0; i < a.size(); i++) 
        current = a[i];
        count = 0;
        for (int j = 0; j < a.size(); j++) 
            if (a[j] == current)
                count ++;
        
        if (count > a.size()/2)
            return 1;
    
    return -1;


int main() 
//    std::cin >> n;
//    vector<int> a(n);
//    for (size_t i = 0; i < a.size(); ++i) 
//        std::cin >> a[i];
//    
//    std::cout << (get_majority_fast(a, 0, a.size()) != -1) << '\n';

    while(true)
        int one, two;
        int n = rand() % 100 ;
        std::cout << n << "\n";
        vector<int> a;
        for (int i = 0; i < n; ++i) 
            a.push_back(rand() % 100);
        

        one = get_majority_element(a, 0, a.size());
        two = get_majority_fast(a,  0, a.size() != -1);

        if (one != two) 
            std::cout << "Wrong answer: " << one << ' ' << two << "\n";
            break;
        
        else 
            std::cout << "OK\n";
        
    

【问题讨论】:

为什么get_majority_fast() 不使用leftright 参数?你为什么要传递一个布尔值作为 right 参数? 在调试器下运行程序。当它因为错误而停止时,检查堆栈跟踪以查看错误的语句,以及变量的值是什么。可能是因为你在vector之外访问。 使用std::vector 时最好的调试工具之一是使用at() 函数。如果您超出向量范围,它将引发异常。你在这里这样做:b_right[i] = a[m + i];——把它改成b_right[i] = a.at(m + i),你应该得到一个std::out_of_range异常just as this example shows @Barmar,我写得相当快get_majority_fast,所以我只是复制粘贴了之前的函数定义。不过,传递给它的论点是无关紧要的。我会检查是否越界,谢谢。 @PaulMcKenzie 您能否提供一个输入,在这种情况下会发生这种情况?到目前为止,我一直得到正确的输出,没有任何越界异常(使用a[m+i] 【参考方案1】:

其中一个循环实际上存在越界错误。更正的循环如下:

for (int i = m; i < right - m ; i++) 
    b_right.at(m-i) = a.at(m + i);

我认为奇怪的 SIGABRT 错误是由于一些神秘的东西。猜猜我学会了使用x.at()

此外,我还有其他几个错误。完整的更正代码如下:

#include <algorithm>
#include <iostream>
#include <vector>


using std::vector;

int get_majority_element(vector<int> &a, int left, int right) 


    int m;
    int majority_left = -1, majority_right = -1;      // majority element in either sub array
    int count_right = 0, count_left = 0;    // count for above
    int new_left, new_right;                      // endpoints

    if (a.size() == 1) 
        return a[0];
    
    else 


        m = (a.size())/2;  // calculate mid point

        vector<int> b_left(m);
        vector<int> b_right(right - m);


        // get left sub array
        for (int i = 0; i < m; i++) 
            b_left.at(i) = a.at(i);
        

        for (int i = 0; i < a.size() - m ; i++) 
            b_right.at(i) = a.at(i + m);
        

        // set new endpoints
        new_left = 0;
        new_right = m;
        majority_left = get_majority_element(b_left, new_left, new_right);


        new_left = m;
        new_right = right - m;

        majority_right = get_majority_element(b_right, new_left, new_right);


        // if there is a majority element, count its frequency

        if (majority_left != -1) 
            for (int i = 0; i < a.size(); i++) 
                if (a[i] == majority_left)
                    count_left++;
            
        

        if (majority_right != -1) 
            for (int i = 0; i < a.size(); i++) 
                if (a[i] == majority_right)
                    count_right++;
            
        


        // if both elements in sub arrays are majority and they're different, there is no majority element
        if (count_left == count_right && majority_left != majority_right) 
            return 0;
        
        else if (count_left == count_right)
            return majority_left;
        // check if either sub array has a majority element that occurs more than n/2 times
        else if (count_right > count_left && count_right > a.size()/2) 
                return majority_right;
        
        else if (count_left > count_right && count_left > a.size()/2)
            return majority_left;
        
            // majority element in sub arrays isn't majority in array
        else
            return 0;
    




int get_majority_fast(vector<int> &a, int left, int right)

    std::reverse(a.begin(),a.end());

    int current = 0;
    int count;
    for (int i = 0; i < a.size(); i++) 
        current = a[i];
        count = 0;
        for (int j = 0; j < a.size(); j++) 
            if (a[j] == current)
                count ++;
        
        if (count > a.size()/2)
            return 1;
    
    return -1;


int main() 

    int n;
    std::cin >> n;
    vector<int> a(n);

    for (size_t i = 0; i < a.size(); ++i) 
        std::cin >> a[i];
    

    int result;
    int out;

    result = get_majority_element(a, 0, a.size());

    if (result != 0)
        out = 1;
    else
        out = 0;
    std::cout << out << '\n';



我确信我可以让它更漂亮,但现在我暂时不想听到这件事。

【讨论】:

以上是关于SIGABRT(信号 6)在使用分而治之的数组中查找多数元素时出错的主要内容,如果未能解决你的问题,请参考以下文章

来自 asyncTask 的 Android 致命信号 6 (SIGABRT)

相机崩溃:带有 JNI 代码的致命信号 6 (SIGABRT)

NestedScrollView 中的 WebView 给出致命信号 6 (SIGABRT) 代码 -6 RenderThread

AsyncTask Android 中的致命信号 6 (SIGABRT)

pycharm 随机发生错误:进程以退出代码 134 完成(被信号 6 中断:SIGABRT)

Android WebRTC 随机崩溃,致命信号 6 (SIGABRT)、tid 1191 (TimeCheckThread) 中的代码 -6 (SI_TKILL)、pid 656 (audioser