В вашем коде есть несколько ошибок. Для начинающих,
непонятно, что означают to
и from
: включительно или
эксклюзив. И если они оба включительно (что ваши аргументы
на рекурсивные вызовы, кажется, предлагает), как вы обнаруживаете
конец. А что значит test
? Вы, кажется, используете это как
критерий конца, когда вы не можете найти слово, но я не понимаю, как.
Если бы я писал это, я бы использовал простой вспомогательный класс для хранения
цель и список слов (но вы можете просто распространять их
явно), и функция-обертка, чтобы клиентский код
не нужно указывать аргументы to
и from
. Там в
нет необходимости в глобальной переменной или каких-либо дополнительных test
. А также
Я бы использовал полуоткрытые интервалы, которые являются идиоматическими в C ++: ниже
переплет включительно, верхний переплет эксклюзив (так top == bottom
указывает пустой диапазон, поэтому я закончил, не найдя
элемент): * 1 010 *
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() );
}
Обратите внимание, что вы не можете сделать сравнение до того, как
диапазон не равен; это приведет к выходу за границы, если все
элементов меньше цели.
Также: я предполагаю, что вы делаете это по педагогическим причинам.
В противном случае, вы должны просто использовать функцию в стандарте
библиотека. И я бы не стал использовать здесь рекурсию:
простое итеративное решение:
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() );
}
(Наконец, вы заметите, что я преобразовал ваши параметры в
Рекомендации. Это ничего не меняет в логике
код, но если words
относительно большой, это будет очень
значительное влияние на производительность.)