2011-01-05 2 views
31

Есть find() функция для списка, как было в векторе?Как найти элемент в списке stl?

Есть ли способ сделать это в списке?

+2

'станда: : vector' имеет метод 'find()'? Это новость для меня. –

+0

mybad ... i означает fint (vectoriterator.begin(), vectoriterator.end(), string) –

+2

Вы правы, 'std :: vector' не имеет метода' find() '. – Raedwald

ответ

80

Вы используете std::find от <algorithm>, который работает одинаково хорошо для std::list и std::vector. std::vector не имеет собственной функции поиска/поиска.

#include <list> 
#include <algorithm> 

int main() 
{ 
    std::list<int> ilist; 
    ilist.push_back(1); 
    ilist.push_back(2); 
    ilist.push_back(3); 

    std::list<int>::iterator findIter = std::find(ilist.begin(), ilist.end(), 1); 
} 

Обратите внимание, что это работает для встроенных типов, таких как int, а также стандартных типов библиотек, как std::string по умолчанию, потому что они имеют operator== при условии, для них. Если вы используете с помощью std::find на контейнере, определенного пользователем типа, вы должны перегрузить operator==, чтобы std::find работать должным образом: EqualityComparable concept

+0

Какова временная сложность 'std :: find()'? Возможно, O (n)? –

+2

Нет возможности бинарного seach для сортированного контейнера? Ленивая реализация. – LDS

+3

@LDS - 'std :: binary_search' обеспечивает двоичный поиск. – birryree

16

Нет, не непосредственно в самом шаблоне станд :: список. Однако вы можете использовать алгоритм std :: find:

std::list<int> my_list; 
//... 
int some_value = 12; 
std::list<int>::iterator iter = std::find (my_list.begin(), my_list.end(), some_value); 
// now variable iter either represents valid iterator pointing to the found element, 
// or it will be equal to my_list.end() 
3

Что вы можете делать, и что вам нужно делать, это разные вопросы.

Если список очень короткий, или вы когда-либо собираетесь называть один раз, используйте линейный подход выше.

Однако линейный поиск является одним из самых больших зол, которые я нахожу в медленном коде, и рассмотрим использование упорядоченной коллекции (набор или мультимножество, если вы разрешаете дубликаты). Если вам нужно вести список по другим причинам, например, используя технику LRU или вам нужно поддерживать порядок вставки или какой-либо другой порядок, создайте для него индекс. Вы действительно можете это сделать, используя std :: set итераторов списка (или мультимножество), хотя вам нужно поддерживать это в любое время, когда ваш список будет изменен.

6

Помимо использования зОго :: найти (из алгоритма), вы можете также использовать std::find_if (который ИМО лучше, станд :: найти), или другой алгоритм находит из this list


#include <list> 
#include <algorithm> 
#include <iostream> 

int main() 
{ 
    std::list<int> myList{ 5, 19, 34, 3, 33 }; 


    auto it = std::find_if(std::begin(myList), 
          std::end(myList), 
          [&](const int v){ return 0 == (v % 17); }); 

    if (myList.end() == it) 
    { 
     std::cout << "item not found" << std::endl; 
    } 
    else 
    { 
     const int pos = std::distance(myList.begin(), it) + 1; 
     std::cout << "item divisible by 17 found at position " << pos << std::endl; 
    } 
} 
+0

Почему find_if лучше? Если вы ищете элемент, который соответствует равенству, вы говорите, что не используете find и будете использовать find_if вместо этого? find_if действительно позволяет вам выполнять поиск по обычаю, но если вам нужно было поместиться в какой-то ужасный функтор, чтобы искать равные, это сделало бы код очень уродливым по сравнению с использованием find. – CashCow

+1

@CashCow Все зависит от того, какой тип элемента находится в векторе или списке. Иногда невозможно использовать std :: find. –

+0

Да, иногда вам нужно find_if, поэтому он является частью библиотеки, но это не делает его «лучше» таким, что вы его используете, даже когда std :: find работает. – CashCow

Смежные вопросы