Меню сайта |
|
|
Категория |
|
|
Развлечение |
|
|
ON - LINE |
|
|
Опрос |
|
|
Оbserver Ward |
Онлайн всего: 1 Гостей: 1 Пользователей: 0
|
|
Друзья сайта |
|
|
Hаша кнопка |
Для обмена банерами , наша кнопка для размещения у вас на сайте
|
|
|
21. Обобщенные алгоритмы в алфавитном порядке (2)
Алгоритм find()
template< class InputIterator, class T > InputIterator find( InputIterator first, InputIterator last, const T &value );
Элементы из диапазона, ограниченного парой итераторов [first,last), сравниваются со значением value с помощью оператора равенства, определенного для типа элементов контейнера. Как только соответствие найдено, поиск прекращается. find() возвращает итератор типа InputIterator, указывающий на найденный элемент; в противном случае возвращается last.
#include <algorithm> #include <iostream.h> #include <list> #include <string> int main() { int array[ 17 ] = { 7,3,3,7,6,5,8,7,2,1,3,8,7,3,8,4,3 }; int elem = array[ 9 ]; int *found_it; found_it = find( &array[0], &array[17], elem );
// печатается: поиск первого вхождения 1 найдено!
cout << "поиск первого вхождения " << elem < <"\t" << ( found_it ? "найдено!\n" : "не найдено!\n" );
string beethoven[] = { "Sonata31", "Sonata32", "Quartet14", "Quartet15", "Archduke", "Symphony7" };
string s_elem( beethoven[ 1 ] );
list< string, allocator > slist( beethoven, beethoven+6 ); list< string, allocator >::iterator iter;
iter = find( slist.begin(), slist.end(), s_elem );
// печатается: поиск первого вхождения Sonata32 найдено!
cout << "поиск первого вхождения " << s_elem << "\t" << ( found_it ? "найдено!\n" : "не найдено!\n" ); }
Алгоритм find_if()
template< class InputIterator, class Predicate > InputIterator find_if( InputIterator first, InputIterator last, Predicate pred );
К каждому элементу из диапазона [first,last) последовательно применяется предикат pred. Если он возвращает true, поиск прекращается. find_if() возвращает итератор типа InputIterator, указывающий на найденный элемент; в противном случае возвращается last.
#include <algorithm> #include <list> #include <set> #include <string> #include <iostream.h>
// альтернатива оператору равенства // возвращает true, если строка содержится в объекте-члене FriendSet class OurFriends { // наши друзья public: bool operator()( const string& str ) { return ( friendset.count( str )); } static void FriendSet( const string *fs, int count ) { copy( fs, fs+count, inserter( friendset, friendset.end() )); } private: static set< string, less<string>, allocator > friendset; }; set< string, less<string>, allocator > OurFriends::friendset;
int main() { string Pooh_friends[] = { "Пятачок", "Тигра", "Иа-Иа" }; string more_friends[] = { "Квазимодо", "Чип", "Пятачок" }; list<string,allocator> lf( more_friends, more_friends+3 );
// заполнить список друзей Пуха OurFriends::FriendSet( Pooh_friends, 3 ); list<string,allocator>::iterator our_mutual_friend; our_mutual_friend = find_if( lf.begin(), lf.end(), OurFriends()); // печатается: // Представьте-ка, наш друг Пятачок - также друг Пуха. if ( our_mutual_friend != lf.end() ) cout << "Представьте-ка, наш друг " << *our_mutual_friend << " также друг Пуха.\n"; return 0; }
Алгоритм find_end()
template< class ForwardIterator1, class ForwardIterator2 > ForwardIterator1 find_end( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2 );
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > ForwardIterator1 find_end( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred );
В последовательности, ограниченной итераторами [first1,last1), ведется поиск последнего вхождения последовательности, ограниченной парой [first2,last2). Например, если первая последовательность - это Mississippi, а вторая - ss, то find_end() возвращает итератор, указывающий на первую s во втором вхождении ss. Если вторая последовательность не входит в первую, то возвращается last1. В первом варианте используется оператор равенства, определенный для типа элементов контейнера, а во втором - бинарный предикат, переданный пользователем.
#include <algorithm> #include <vector> #include <iostream.h> #include <assert.h> int main() { int array[ 17 ] = { 7,3,3,7,6,5,8,7,2,1,3,7,6,3,8,4,3 }; int subarray[ 3 ] = { 3, 7, 6 }; int *found_it;
// find найти последнее вхождение последовательности 3,7,6 // в массив и вернуть адрес первого ее элемента ...
found_it = find_end( &array[0], &array[17], &subarray[0], &subarray[3] ); assert( found_it == &array[10] ); vector< int, allocator > ivec( array, array+17 ); vector< int, allocator > subvec( subarray, subarray+3 ); vector< int, allocator >::iterator found_it2;
found_it2 = find_end( ivec.begin(), ivec.end(), subvec.begin(), subvec.end(), equal_to<int>() ); assert( found_it2 == ivec.begin()+10 );
cout << "ok: find_end правильно вернула начало " << "последнего вхождения последовательности: 3,7,6!\n"; }
Алгоритм find_first_of()
template< class ForwardIterator1, class ForwardIterator2 > ForwardIterator1 find_first_of( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2 );
template< class ForwardIterator1, class ForwardIterator2, class BinaryPredicate > ForwardIterator1 find_first_of( ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred );
Последовательность, ограниченная парой [first2,last2), содержит элементы, поиск которых ведется в последовательности, ограниченной итераторами [first1,last1). Допустим, нужно найти первую гласную в последовательности символов synesthesia. Для этого определим вторую последовательность как aeiou. find_first_of() возвращает итератор, указывающий на первое вхождение любого элемента последовательности гласных букв, в данном случае e. Если же первая последовательность не содержит ни одного элемента из второй, то возвращается last1. В первом варианте используется оператор равенства, определенный для типа элементов контейнера, а во втором - бинарный предикат pred.
#include <algorithm> #include <vector> #include <string> #include <iostream.h> int main() { string s_array[] = { "Ee", "eE", "ee", "Oo", "oo", "ee" };
// возвращает первое вхождение "ee" -- &s_array[2] string to_find[] = { "oo", "gg", "ee" }; string *found_it = find_first_of( s_array, s_array+6, to_find, to_find+3 ); // печатается: // найдено: ee // &s_array[2]: 0x7fff2dac // &found_it: 0x7fff2dac
if ( found_it != &s_array[6] ) cout << "найдено: " << *found_it << "\n\t" << "&s_array[2]:\t" << &s_array[2] << "\n\t" << "&found_it:\t" << found_it << "\n\n"; vector< string, allocator > svec( s_array, s_array+6); vector< string, allocator > svec_find( to_find, to_find+2 ); // возвращает вхождение "oo" -- svec.end()-2 vector< string, allocator >::iterator found_it2;
found_it2 = find_first_of( svec.begin(), svec.end(), svec_find.begin(), svec_find.end(), equal_to<string>() );
// печатает: // тоже найдено: oo // &svec.end()-2: 0x100067b0 // &found_it2: 0x100067b0
if ( found_it2 != svec.end() ) cout << "тоже найдено: " << *found_it2 << "\n\t" << "&svec.end()-2:\t" << svec.end()-2 << "\n\t" << "&found_it2:\t" << found_it2 << "\n"; }
Алгоритм for_each()
template< class InputIterator, class Function > Function for_each( InputIterator first, InputIterator last, Function func );
for_each() применяет объект-функцию func к каждому элементу в диапазоне [first,last). func не может изменять элементы, поскольку итератор записи не гарантирует поддержки присваивания. Если же модификация необходима, следует воспользоваться алгоритмом transform(). func может возвращать значение, но оно игнорируется.
#include <algorithm> #include <vector> #include <iostream.h>
template <class Type> void print_elements( Type elem ) { cout << elem < <" "; } int main() { vector< int, allocator > ivec;
for ( int ix = 0; ix < 10; ix++ ) ivec.push_back( ix ); void (*pfi)( int ) = print_elements; for_each( ivec.begin(), ivec.end(), pfi ); return 0; }
Алгоритм generate()
template< class ForwardIterator, class Generator > void generate( ForwardIterator first, ForwardIterator last, Generator gen );
generate() заполняет диапазон, ограниченный парой итераторов [first,last), путем последовательного вызова gen, который может быть объектом-функцией или указателем на функцию.
#include <algorithm> #include <list> #include <iostream.h> int odd_by_twos() { static int seed = -1; return seed += 2; } template <class Type> void print_elements( Type elem ) { cout < < elem < < " "; } int main() { list< int, allocator > ilist( 10 ); void (*pfi)( int ) = print_elements; generate( ilist.begin(), ilist.end(), odd_by_twos );
// печатается: // элементы в списке, первый вызов: // 1 3 5 7 9 11 13 15 17 19
cout < < "элементы в списке, первый вызов:\n"; for_each( ilist.begin(), ilist.end(), pfi ); generate( ilist.begin(), ilist.end(), odd_by_twos );
// печатается: // элементы в списке, второй вызов: // 21 23 25 27 29 31 33 35 37 39 cout < <"\n\nэлементы в списке, второй вызов:\n"; for_each( ilist.begin(), ilist.end(), pfi ); return 0; }
Алгоритм generate_n()
template< class OutputIterator, class Size, class Generator > void generate_n( OutputIterator first, Size n, Generator gen );
generate_n() заполняет последовательность, начиная с first, n раз вызывая gen, который может быть объектом-функцией или указателем на функцию.
#include <algorithm> #include <iostream.h> #include <list> class even_by_twos { public: even_by_twos( int seed = 0 ) : _seed( seed ){} int operator()() { return _seed += 2; } private: int _seed; };
template <class Type> void print_elements( Type elem ) { cout << elem << " "; }
int main() { list< int, allocator > ilist( 10 ); void (*pfi)( int ) = print_elements;
generate_n( ilist.begin(), ilist.size(), even_by_twos() );
// печатается: // generate_n с even_by_twos(): // 2 4 6 8 10 12 14 16 18 20
cout << "generate_n с even_by_twos():\n"; for_each( ilist.begin(), ilist.end(), pfi ); cout << "\n"; generate_n( ilist.begin(), ilist.size(), even_by_twos( 100 ) );
// печатается: // generate_n с even_by_twos( 100 ): // 102 104 106 108 110 112 114 116 118 120
cout << "generate_n с even_by_twos( 100 ):\n"; for_each( ilist.begin(), ilist.end(), pfi ); }
Алгоритм includes()
template< class InputIterator1, class InputIterator2 > bool includes( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2 );
template< class InputIterator1, class InputIterator2, class Compare > bool includes( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, Compare comp );
includes() проверяет, каждый ли элемент последовательности [first1,last1) входит в последовательность [first2,last2). Первый вариант предполагает, что последовательности отсортированы в порядке, определяемом оператором "меньше”; второй - что порядок задается параметром-типом comp.
#include <algorithm> #include <vector> #include <iostream.h> int main() { int ia1[] = { 13, 1, 21, 2, 0, 34, 5, 1, 8, 3, 21, 34 }; int ia2[] = { 21, 2, 8, 3, 5, 1 }; // алгоритму includes следует передавать отсортированные контейнеры sort( ia1, ia1+12 ); sort( ia2, ia2+6 );
// печатает: каждый элемент ia2 входит в ia1? Да
bool res = includes( ia1, ia1+12, ia2, ia2+6 ); cout < < "каждый элемент ia2 входит в ia1? " < <(res ? "Да" : "Нет") < < endl;
vector< int, allocator > ivect1( ia1, ia1+12 ); vector< int, allocator > ivect2( ia2, ia2+6 );
// отсортирован в порядке убывания sort( ivect1.begin(), ivect1.end(), greater<int>() ); sort( ivect2.begin(), ivect2.end(), greater<int>() ); res = includes( ivect1.begin(), ivect1.end(), ivect2.begin(), ivect2.end(), greater<int>() );
// печатает: каждый элемент ivect2 входит в ivect1? Да
cout < < "каждый элемент ivect2 входит в ivect1? " < < (res ? "Да" : "Нет") < < endl;
}
Алгоритм inner_product()
template< class InputIterator1, class InputIterator2 class Type > Type inner_product( InputIterator1 first1, InputIterator1 last, InputIterator2 first2, Type init );
template< class InputIterator1, class InputIterator2 class Type, class BinaryOperation1, class BinaryOperation2 > Type inner_product( InputIterator1 first1, InputIterator1 last, InputIterator2 first2, Type init, BinaryOperation1 op1, BinaryOperation2 op2 );
Первый вариант суммирует произведения соответственных членов обеих последовательностей и прибавляет результат к начальному значению init. Первая последовательность ограничена итераторами [first1,last1), вторая начинается с first2 и обходится синхронно с первой. Например, если даны последовательности {2,3,5,8} и {1,2,3,4}, то результат вычисляется следующим образом:
2*1 + 3*2 + 5*3 + 8*4
Если начальное значение равно 0, алгоритм вернет 55.
Во втором варианте вместо сложения используется бинарная операция op1, а вместо умножения - бинарная операция op1. Например, если для приведенных выше последовательностей применить вычитание в качестве op1 и сложение в качестве op2, то результат будет вычисляться так:
(2+1) - (3+2) - (5+3) - (8+4)
inner_product() - это один из численных алгоритмов. Для его использования в программу необходимо включить заголовочный файл .
#include <numeric> #include <vector> #include <iostream.h> int main() { int ia[] = { 2, 3, 5, 8 }; int ia2[] = { 1, 2, 3, 4 };
// перемножить пары элементов из обоих массивов, // сложить и добавить начальное значение: 0
int res = inner_product( &ia[0], &ia[4], &ia2[0], 0 );
// печатает: скалярное произведение массивов: 55 cout << "скалярное произведение массивов: " << res << endl; vector<int, allocator> vec( ia, ia+4 ); vector<int, allocator> vec2( ia2, ia2+4 );
// сложить пары элементов из обоих векторов, // вычесть из начального значения: 0
res = inner_product( vec.begin(), vec.end(), vec2.begin(), 0, minus<int>(), plus<int>() );
// печатает: скалярное произведение векторов: -28 cout << "скалярное произведение векторов: " << res << endl; return 0; }
Алгоритм inplace_merge()
template <class BidirectionalIterator > void inplace_merge( BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last );
template< class BidirectionalIterator, class Compare > void inplace_merge( BidirectionalIterator first, BidirectionalIterator middle, BidirectionalIterator last, Compare comp );
inplace_merge() объединяет две соседние отсортированные последовательности, ограниченные парами итераторов [first,middle) и [middle,last). Результирующая последовательность затирает исходные, начиная с позиции first. В первом варианте для упорядочения элементов используется оператор "меньше”, определенный для типа элементов контейнера, во втором - операция сравнения, переданная программистом.
#include <algorithm> #include <vector> #include <iostream.h> template <class Type> void print_elements( Type elem ) { cout << elem << " "; }
/* * печатает: ia разбит на два отсортированных подмассива: 12 15 17 20 23 26 29 35 40 51 10 16 21 41 44 54 62 65 71 74
ia inplace_merge: 10 12 15 16 17 20 21 23 26 29 35 40 41 44 51 54 62 65 71 74
ivec разбит на два отсортированных подвектора: 51 40 35 29 26 23 20 17 15 12 74 71 65 62 54 44 41 21 16 10
ivec inplace_merge: 74 71 65 62 54 51 44 41 40 35 29 26 23 21 20 17 16 15 12 10 */
int main() { int ia[] = { 29,23,20,17,15,26,51,12,35,40, 74,16,54,21,44,62,10,41,65,71 };
vector< int, allocator > ivec( ia, ia+20 ); void (*pfi)( int ) = print_elements;
// отсортировать обе подпоследовательности sort( &ia[0], &ia[10] ); sort( &ia[10], &ia[20] ); cout << "ia разбит на два отсортированных подмассива: \n"; for_each( ia, ia+20, pfi ); cout << "\n\n";
inplace_merge( ia, ia+10, ia+20 ); cout << "ia inplace_merge:\n"; for_each( ia, ia+20, pfi ); cout << "\n\n";
sort( ivec.begin(), ivec.begin()+10, greater<int>() ); sort( ivec.begin()+10, ivec.end(), greater<int>() ); cout << "ivec разбит на два отсортированных подвектора: \n"; for_each( ivec.begin(), ivec.end(), pfi ); cout << "\n\n";
inplace_merge( ivec.begin(), ivec.begin()+10, ivec.end(), greater<int>() ); cout << "ivec inplace_merge:\n"; for_each( ivec.begin(), ivec.end(), pfi ); cout << endl; }
|
Категория: С++ | Добавил: r2d2 (29.09.2011)
|
Просмотров: 746
| Рейтинг: 0.0/0 |
Добавлять комментарии могут только зарегистрированные пользователи. [ Регистрация | Вход ]
|
|
Born in Ussr |
|
|
Залогиниться |
|
|
Турниры |
|
|
|