哪个更好?
根据Savitch的说法,每个递归都以激活帧的形式保存在堆栈中。这有开销。但是,编写递归版本需要少量代码。对于一个最好上交的面试。两者的代码都在下面。
#include <iostream>
using namespace std;
const int SIZE = 10;
int array[ SIZE ] = { 0,1,2,3,4,5,6,7,8,9 };
int answer = NULL;
void binary_search_recursive( int array[], int start, int end, int value, int& answer )
{
int mid = (start + end ) / 2;
if ( array[ mid ] == value )
{
answer = mid;
}
else if ( array[ mid ] < value )
{
binary_search_recursive( array, mid + 1, end, value, answer );
}
else
{
binary_search_recursive( array, start, mid - 1, value, answer );
}
}
void binary_search_iterative( int array[], int start, int end, int value, int& answer )
{
int mid = ( (start + end ) / 2 );
while( array[ mid ] != value )
{
if ( array[ mid ] < value )
{
start = mid;
mid = ( ( ( mid + 1 ) + end ) / 2 );
}
else
{
end = mid;
mid = ( ( start + ( mid - 1 ) ) / 2 );
}
}
answer = mid;
}
int main()
{
binary_search_iterative( array, 0, SIZE - 1, 4, answer);
cout << answer;
return 0;
}
答案 0 :(得分:4)
算法的递归版本通常在代码行中更短,但由于递归版本的函数调用开销,相同算法的迭代版本通常通常更快。 / p>
关于二进制搜索算法,更快的实现被编写为迭代。例如,Jon Bentley发布的二进制搜索版本是迭代的。
答案 1 :(得分:2)
在二进制搜索的情况下,递归并不能比迭代更好地表达你的意图,所以迭代方法更好。
我认为面试的最佳方法是提交一个调用lower_bound
的解决方案:它向采访者显示您不仅知道一些基本语法以及如何编写一年级算法,而且你不要浪费时间重写样板代码。
答案 2 :(得分:1)
如果速度是一个问题或者堆栈大小有限制,则使用迭代,因为正如您所说,它涉及重复调用该函数,这会导致它占用堆栈上更多的空间。至于在面试中回答我会选择当时最简单的做法,原因显而易见:))
答案 3 :(得分:1)
对于一次采访,我首先要提到递归和迭代解决方案都是可能的,同样也很容易写。递归版本存在嵌套堆栈帧的潜在问题,使用甚至耗尽堆栈内存(并将不同页面错误地放入缓存中),但编译器倾向于提供尾递归优化,从而有效地创建迭代实现。递归函数往往更加明显无误,但是在日常的C ++编程中并没有那么广泛适用,所以对维护程序员来说可能不那么熟悉和舒适。
除非有理由不在实际项目中使用std::binary_search
中的<algorithm>
(http://www.sgi.com/tech/stl/binary_search.html)。< / p>
为了说明尾递归,您的binary_search_recursive算法已由g++ -O4 -S
更改为下面的程序集。注意:
movl
是寄存器和存储器之间的移动语句(赋值)(“long”的尾随“l”反映寄存器/存储器位置中的位数)subl
,shrl
,sarl
,cmpl
是减法,右移,右移算术和比较指令,重要的是要注意的是副作用他们设置了一些标志,如“等于”,如果他们产生0结果,由je
(如果等于跳跃)和jge
(如果大于或等于跳跃),{{{ 1}}如果不相等就跳。jne
终止条件,而L14和L4处的代码处理递归步骤,可以跳回L12。这是你的binary_search_recursive函数的反汇编(名称以C ++风格破坏)......
answer = mid