There are several things wrong with your code. For starters,
it's not clear what to and from mean: are they inclusive, or
exclusive. And if they're both inclusive (which your arguments
to the recursive calls seems to suggest), how do you detect the
end. And what does test mean? You seem to be using it as an
end criterion when you don't find the word, but I don't see how.
If I were writing this, I'd use a simple helper class to hold
the target and the word list (but you can just propagate them
down explicitly), and a wrapper function so that the client code
doesn't have to specify the to and from arguments. There's
no need for a global variable, or any additional test. And
I'd use the half open intervals that are idiomatic in C++: lower
bound inclusive, upper bound exclusive (so top == bottom
specifies an empty range, so I've finished without finding the
element):
bool
binSearch( std::string const& target,
std::vector<std::string> const& words );
namespace {
class BinSearcher
{
std::vector<std::string> const& myWords;
std::string const& myTarget;
bool doSearch( int bottom, int top ) const
{
int mid = (top - bottom) / 2;
return mid != top
&& (myTarget == myWords[mid]
|| (myTarget > myWords[mid] && doSearch( mid + 1, top ))
|| (myTarget < myWords[mid] && doSearch( bottom, mid ));
}
BinSearcher( std::string const& target,
std::vector<std::string> const& words )
: myWords( words )
, myTarget( target )
{
}
friend bool binSearch( std::string const&,
std::vector<std::string> const& );
};
}
bool
binSearch( std::string const& target,
std::vector<std::string> const& words )
{
BinSearcher searcher( target, words );
return searcher.doSearch( 0, words.size() );
}
Note that you can't do the comparison before testing that the
range isn't equal; it will cause an out of bounds access if all
of the elements are less than the target.
Also: I presume that you're doing this for pedagogical reasons.
Otherwise, you should just use the function in the standard
library. And I wouldn't normally use recursion here: there's
a straightforward iterative solution:
namespace {
bool
doBinSearch( std::string const& target,
std::vector<std::string> const& words,
int bottom,
int top )
{
bool found = false;
while ( bottom != top && ! found ) {
int mid = (top - bottom) / 2;
int cmp = target.compare( words[mid] );
if ( cmp < 0 ) {
top = mid ;
} else if ( 0 < cmp ) {
bottom = mid + 1;
} else {
found = true;
}
}
return found;
}
}
bool
binSearch( std::string const& target,
std::vector<std::string> const& words )
{
return doBinSearch( target, words, 0, words.size() );
}
(Finally, you'll notice that I've converted your parameters to
references. It doesn't change anything in the logic of the
code, but if words is relatively large, it will make a very
significant impact on the performance.)
std::binary_search. Is the signature fixed? It would be more elegant to use an iterator-based solution.constreference to the vector instead of a copy.