为什么我会出现分段错误以及如何解决它

时间:2016-02-25 19:17:40

标签: c++ algorithm binary segmentation-fault binary-search

#include<iostream>
using namespace std;
int BSearch(int array[],int key,int left,int right)
{
    if(array[left+right/2]==key)
        cout<<left+right/2;
    else if(array[left+right/2]<key)
        BSearch(array,key,left,right/2-1);
    else 
        BSearch(array,key,right/2,right);

}

int main()
{
int list[]={1,2,3,4,5,6,7,8,9,11,15,21};
BSearch(list,5,0,sizeof(list)/sizeof(int)-1);
}

我写了这个程序来执行二进制搜索。每次运行时都会出现Segmentation故障。

4 个答案:

答案 0 :(得分:4)

点击此处:

if(array[left+right/2]==key)

并专注于此left+right/2。在这里,运营商的优先权发挥作用。你可能意味着左右添加,然后将总和除以2。

然而,它首先将两个除以然后将其加到左边。

所以改变:

left+right/2

为:

(left+right)/2

到处你需要。

而且,你的逻辑是有缺陷的。我已在Binary Search (C++)中编写了一个示例,但即使是Wikipedia也可以提供帮助。您的代码适用于此:

#include <iostream>
using namespace std;

void BSearch(int array[], int key, int left, int right) {
    if (array[(left + right) / 2] == key) {
        cout << "found at position " << (left + right) / 2;
        return;
    } else if (array[(left + right) / 2] > key) {
        BSearch(array, key, left, (left + right)/ 2 - 1);
    } else {
        BSearch(array, key,  (left + right)/ 2 + 1, right);
    }
}

int main() {
    int list[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 15, 21};
    BSearch(list, 5, 0, sizeof(list) / sizeof(int) - 1);
}

输出:

found at position 4

答案 1 :(得分:1)

实际上,正确的方法不是

(left+right)/2

left + (right - left)/2

区别在于使用大型列表时,第一个变量存在溢出问题(带有有符号整数的未定义行为,无法按预期使用无符号)。

让我们说明char类型的范围为0..255 unsigned和-128..127 signed(int只是范围更广但问题仍然存在)。

假设您要查找签名字符40和100的中间位置:

  • 第一个表达式[(left+right)/2]的结果是:(40+100)/2 = (-116)/2 = -58(技术上未定义,40 + 100个字符只有-116,标准的两个补码实现但不是由C / C ++标准强制执行)
  • 第二个[left + (right - left)/2]的结果是40 + (100-40)/2 = 40 + (60)/2 = 40 + 30 = 70

使用unsigned char 100和250:

  • 第一个:(100 + 250)/2 = (94)/2 = 47
  • 第二个:100 + (250 - 100)/2 = 100 + 150 / 2 = 175

对于递归调用,您需要在&#34; middle&#34;中提供范围。点(再次L + (R-L)/2而不是R/2)。

特别是,如Wikipedia article中所述:

  

虽然二元搜索的基本思想是比较的   直截了当,细节可以令人惊讶地棘手......(Donald Knuth)

答案 2 :(得分:0)

您必须更改小于大于秒的if语句:else if(array[(left+right)/2]>key),因为您搜索反面。

您必须在第三个if语句中将right/2更改为(left+right)/2,因为左边可能不是0而right/2不会更正。你必须从midle到riht侧搜索。解决方案是

#include <iostream>

using namespace std;

int BSearch(int array[],int key,int left,int right)
{
    if(array[(left+right)/2]==key)
        cout<<(left+right)/2 << endl;
    else if(array[(left+right)/2]>key)
        BSearch(array,key,left,(left+right)/2-1);
    else 
        BSearch(array,key,(left+right)/2+1,right);
}

int main()
{
    int list[]={1,2,3,4,5,6,7,8,9,11,15,21};
    BSearch(list,5,0,sizeof(list)/sizeof(int)-1);
}

答案 3 :(得分:0)

其他答案中讨论的括号问题肯定是一个大问题,必须修复。但是,我不认为这会导致段错误。

第一次调用BSearch()时,leftright分别为0和11。 5是(错误地)计算的索引,指向值6.结果,调用BSearch()的最后一行,为leftright传递5和11。 / p>

再次通过该功能,再次调用最后一行,再次传递5和11,无限广告

您必须更正BSearch()如何计算要传递给自身的索引。