为什么我会遇到分段错误以及如何解决它
Why am I getting segmentation fault and how to resolve it
#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);
}
我编写了这个程序来执行二进制搜索。每次运行它时,我都会遇到分段错误。
在这里检查:
if(array[left+right/2]==key)
并专注于这个left+right/2
.在这里,运算符的优先级开始发挥作用。您可能的意思是将左加和右相加,然后将总和除以二。
但是,它将首先将右除以二,然后将其添加到左。
所以改变:
left+right/2
自:
(left+right)/2
随处可见。
此外,你的逻辑是有缺陷的。我已经在Binary Search(C++)中写了一个例子,但即使是维基百科也可以在这里提供帮助。你的代码适用于这个:
#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
实际上正确的方法不是
(left+right)/2
但
left + (right - left)/2
不同之处在于,当使用大型列表时,第一个变体存在溢出问题(有符号整数的未定义行为,无符号的未定义行为)。
让我们说明范围为 0..255 无符号和 -128..127 有符号的字符类型(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
使用无符号字符 100 和 250:
- 第一:
(100 + 250)/2 = (94)/2 = 47
- 第二种:
100 + (250 - 100)/2 = 100 + 150 / 2 = 175
对于递归调用,您需要沿"中间"点提供范围(再次L + (R-L)/2
而不是R/2
)。
特别是,正如维基百科文章中也提到的:
虽然二叉搜索的基本思想是相对的 直截了当,细节可能令人惊讶地棘手...(唐纳德·高德纳)
您必须更改为小于秒 if 语句:else if(array[(left+right)/2]>key)
,因为您搜索反面。
并且您必须在第三个 if 语句中将 right/2
更改为 (left+right)/2
,因为 left 可能不为 0,right/2
不会相关。您必须从中间侧搜索到右侧搜索。解决方案是
#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);
}
其他答案中讨论的括号问题当然是一个大问题,必须解决。 但是,我不认为这会导致段错误。
第一次调用 BSearch()
时,left
和 right
分别为 0 和 11。 5 是(错误地)计算的索引,指向值 6。 结果,调用BSearch()
的最后一行,通过 5 和 11 表示 left
和 right
.
遍历函数后,再次调用最后一行,再次传递 5 和 11,无穷大。
必须更正 BSearch()
计算要传递给自身的索引的方式。
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- Ardunio UNO解决了多个重叠的定时器循环
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 两个文件使用彼此的功能-如何解决
- 计算每个节点的树高,帮助我解释这个代码解决方案
- 如何解决"invalid conversion from 'char' to 'const char*'"
- 在java中解决这段代码时面临循环中的问题
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- 难以理解某些人解决IOI问题的源代码
- visual c++,如何获取解决方案目录中的代码
- 如何解决错误:SCIP C++中的 SCIP 阶段无效 <10>
- 节俭并发:未解决的外部问题
- IpOpt拒绝解决不受约束的问题
- 如何解决这个超硬恒星的创造问题
- 循环无限运行C++解决骑士之旅问题
- 有没有办法在远程设备上打开和编辑visual Studio 2017解决方案
- C++Matching Brackets 2解决方案不起作用
- 在 ubuntu3 上C++ goto 定义有什么解决方案吗16.04?
- 为什么这段代码不起作用,我该如何解决?