Which is better?
According to Savitch, each recurse is saved on the stack in the form of an activation frame. This has overhead. However it takes a few less lines of code to write a recursive version. For an interview which one is better to turn in. The code for both is below.
#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;
}
For an interview, I’d start by mentioning that both recursive and iterative solutions are possible and similarly trivial to write. Recursive versions have a potential issue with nested stack frames using or even exhausting stack memory (and faulting different pages into cache), but compilers tend to provide tail recursive optimisations that effectively create an iterative implementation. Recursive functions tend to be more self-evidently correct and concise, but aren’t as widely applicable in day to day C++ programming so may be a little less familiar and comfortable to maintenance programmers.
Unless there’s a reason not to, in a real project I’d use
std::binary_searchfrom<algorithm>(http://www.sgi.com/tech/stl/binary_search.html).To illustrate tail recursion, your binary_search_recursive algorithm was changed to the assembly below by
g++ -O4 -S. Notes:movlare move statements (assignments) between registers and memory (the trailing “l” for “long” reflects the number of bits in the registers/memory locations)subl,shrl,sarl,cmplare subtraction, shift right, shift arithmetic right, and compare instructions, and the important thing to note is that as a side effect they set a few flags, such as “equals” if they produce a 0 result, that is consulted byje(jump if equals) andjge(jump if greater or equal),jnejump if not equal.answer = midtermination condition is handled at L10, while the recursive steps are instead handled by the code at L14 and L4 and may jump back up to L12.Here’s the disassembly of your binary_search_recursive function (the name is mangled in C++ style)…