Программирование. Принципы и практика использования C++ Исправленное издание, стр. 287
{ while (first!=last && *first != val) ++first; return first;}Вы полагаете, что этот цикл вполне тривиален? Мы так не думаем. На самом деле это минимальное, эффективное и непосредственное представление фундаментального алгоритма. Однако, пока мы не рассмотрим несколько примеров, это далеко не очевидно. Сравним несколько версий алгоритма.
template<class In, class T>In find(In first,In last,const T& val) // находит первый элемент в последовательности [first,last], // равный val for (In p = first; p!=last; ++p) if (*p == val) return p; return last;}Эти два определения логически эквивалентны, и хороший компилятор сгенерирует для них обоих одинаковый код. Однако на практике многие компиляторы не настолько хороши, чтобы устранить излишнюю переменную (
pfind()ПОПРОБУЙТЕ
Уверены ли вы, что эти два определения являются логически эквивалентными? Почему? Попробуйте привести аргументы в пользу их эквивалентности. Затем примените оба алгоритма к одному и тому же набору данных. Знаменитый специалист по компьютерным наукам Дон Кнут ((Don Knuth) однажды сказал: “Я только доказал, что алгоритм является правильным, но я его не проверял”. Даже математические доказательства содержат ошибки. Для того чтобы убедиться в своей правоте, нужно иметь как доказательства, так и результаты тестирования.
21.2.1. Примеры использования обобщенных алгоритмов
find()• Алгоритм
find()• Алгоритм
find()Рассмотрим несколько примеров (если они покажутся вам сложными, посмотрите на диаграммы из раздела 20.4).
void f(vector<int>& v,int x) // работает с целочисленными векторами{ vector<int>::iterator p = find(v.begin(),v.end(),x); if (p!=v.end()) { /* мы нашли x */ } // ...}
find()vector<int>::iterator++++first**firstfirst!=last*first!=valПопробуем применить алгоритм к объекту класса
listvoid f(list<string>& v,string x) // работает со списком строк{ list<string>::iterator p = find(v.begin(),v.end(),x); if (p!=v.end()) { /* мы нашли x */ } // ...}
find()list<string>::iteratorvector<int>++++first**firstLinkfirst!=lastLink**first!=val!=stringИтак, алгоритм
find()find()find()void f(Document& v,char x) // работает с объектами класса Document{ Text_iterator p = find(v.begin(),v.end(),x); if (p!=v.end()) { /* мы нашли x */ } // ...}Эта гибкость является отличительной чертой алгоритмов из библиотеки STL и делает их более полезными, чем многие люди могут себе представить.
21.3. Универсальный алгоритм поиска: find_if()
Нам редко приходится искать какое-то конкретное значение. Чаще нас интересует значение, удовлетворяющее определенным критериям. Мы смогли бы выполнять намного более полезную операцию
find42