busca em um vetor é muito lento desde que você tem que olhar para cada elemento do vector de modo considerar o uso de um mapa se você está fazendo um monte de pesquisas
naumcho
7
@naumcho: Se o vetor é classificado, há sempre uma pesquisa binária, conforme publicado abaixo. Isso o torna tão rápido quanto um mapa e, se você estiver armazenando apenas valores (não mapas de chave / valor), utilizará muito menos memória.
21119 Adam Hawes
4
mapas certamente não são a melhor escolha, mas usar set pode ser útil. Se você precisar de tempo de pesquisa O (1), hash_set é o caminho a seguir.
#include<vector>vector<int> vec;//can have other data types instead of int but must same datatype as item
std::find(vec.begin(), vec.end(), item)!= vec.end()
Isso retorna um bool ( truese presente, falsecaso contrário). Com o seu exemplo:
Não vejo como count () pode ser mais rápido que find (), pois find () pára assim que um elemento é encontrado, enquanto count () sempre precisa varrer toda a sequência.
Éric Malenfant
114
Não se esqueça de #include <algorithm>ou então você pode obter erros muito estranhos como 'não consegue encontrar função correspondente no std namespace'
rustyx
80
Não incomodou ninguém que, apesar de o STL ser "orientado a objetos", .find()ainda não é uma função membro std::vector, como seria de esperar? Eu me pergunto se isso é de alguma forma uma conseqüência do modelo.
bobobobo
71
@obobobo: OOP não tem nada a ver com membros versus não-membros. E existe uma ampla escola de pensamento de que, se algo não precisa ser um membro, ou quando não dá nenhuma vantagem quando implementado como um membro, não deve ser um membro; std::vector<>::find()não daria nenhuma vantagem, nem é necessário; portanto, não, não deve ser um membro. Veja também en.wikipedia.org/wiki/Coupling_%28computer_programming%29
Sebastian Mach
36
@phresnel Eu diria que "quando não dá nenhuma vantagem quando implementado como membro" é falso neste caso. A vantagem é uma interface simplificada e clara. Por exemplo: mvec.find(key) != mvec.cend()é preferível std::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend().
swalog
113
Como outros já disseram, use o STL findou find_iffunções. Mas se você está procurando em grandes vetores e isso afeta o desempenho, você pode querer classificar seu vetor e use as binary_search, lower_boundou upper_boundalgoritmos.
Boa resposta! Encontrar é sempre o (n). lower_bound é o (log (n)) se usado com iteradores de acesso aleatório.
Stephen Edmonds
30
A classificação é O (nlogn), portanto, só vale a pena se você estiver fazendo mais que pesquisas O (logn).
Liori
7
@ liori True Depende dos seus padrões de uso. Se você precisar classificá-lo apenas uma vez, faça várias pesquisas repetidamente para salvar você.
Brian Neal
1
@ Brian Neal, a classificação de um vetor grande vale a pena se houver muitas pesquisas de elementos nele. Classificando será O (nlogn) e O (n) será melhor se a pessoa tem que encontrar um elemento apenas uma vez :)
Swapnil B.
47
Use find do cabeçalho do algoritmo de stl. Ilustrei seu uso com o tipo int. Você pode usar qualquer tipo que quiser, desde que possa comparar a igualdade (sobrecarga == se for necessário para sua classe personalizada).
#include<algorithm>#include<vector>usingnamespace std;int main(){typedefvector<int>IntContainer;typedefIntContainer::iteratorIntIterator;IntContainer vw;//...// find 5IntIterator i = find(vw.begin(), vw.end(),5);if(i != vw.end()){// found it}else{// doesn't exist}return0;}
Dependendo das necessidades do OP, find_if () também pode ser apropriado. Permite pesquisar usando um predicado arbitrário em vez de igualdade.
Éric Malenfant
Ops, seu comentário foi tarde demais. A resposta que eu dei também menciona find_if.
Frank
39
Se seu vetor não for solicitado, use a abordagem sugerida pelo MSN:
if(std::find(vector.begin(),vector.end(), item)!=vector.end()){// Found the item}
Se seu vetor for encomendado, use o método binary_search sugerido por Brian Neal:
if(binary_search(vector.begin(),vector.end(), item)){// Found the item}
a pesquisa binária produz O (log n) pior desempenho, o que é muito mais eficiente que a primeira abordagem. Para usar a pesquisa binária, você pode usar qsort para classificar o vetor primeiro e garantir que ele seja ordenado.
A pesquisa binária terá melhor desempenho em contêineres maiores, mas para contêineres pequenos é provável que uma pesquisa linear simples seja tão rápida ou mais rápida.
Observe que você pode se safar com 1 parâmetro de modelo porque pode extrair o value_typedo Container. Você precisa do typenameporque Container::value_typeé um nome dependente .
Observe que isso às vezes é um pouco amplo demais - funcionaria para std :: set por exemplo, mas apresentava um desempenho terrível comparado à função de membro find (). Eu achei melhor adicionar uma especialização para os recipientes com uma pesquisa mais rápida (set / mapa, unordered_ *)
Andy Krouwel
10
Lembre-se de que, se você estiver fazendo muitas pesquisas, existem contêineres STL que são melhores para isso. Não sei qual é a sua aplicação, mas vale a pena considerar contêineres associativos como std :: map.
std :: vector é o contêiner de escolha, a menos que você tenha uma razão para outra e as pesquisas por valor possam ser essa.
Mesmo com pesquisas por valor, o vetor pode ser uma boa escolha, desde que seja classificado e você use binary_search, lower_bound ou upper_bound. Se o conteúdo do contêiner for alterado entre pesquisas, o vetor não será muito bom devido à necessidade de classificar novamente.
Lembre-se de que também existe uma função find_if , que você pode usar se sua pesquisa for mais complexa, ou seja, se você não estiver apenas procurando por um elemento, mas, por exemplo, desejar ver se há um elemento que atenda a um determinado condição, por exemplo, uma sequência que começa com "abc". ( find_ifdaria a você um iterador que aponta para o primeiro elemento desse tipo).
#include<algorithm>#include<vector>// You can use class, struct or primitive data type for ItemstructItem{//Some fields};typedef std::vector<Item>ItemVector;typedefItemVector::iteratorItemIterator;//...ItemVector vtItem;//... (init data for vtItem)Item itemToFind;//...ItemIterator itemItr;
itemItr = std::find(vtItem.begin(), vtItem.end(), itemToFind);if(itemItr != vtItem.end()){// Item found// doThis()}else{// Item not found// doThat()}
Você pode usar a findfunção, encontrada no stdespaço para nome, ie std::find. Você passa a std::findfunção begine o enditerador do vetor que deseja pesquisar, junto com o elemento que você está procurando e compara o iterador resultante ao final do vetor para ver se eles correspondem ou não.
Isso também é útil para pesquisar a sequência de elementos.
#include<algorithm>#include<iostream>#include<vector>template<typenameContainer>bool search_vector(constContainer& vec,constContainer& searchvec){return std::search(vec.begin(), vec.end(), searchvec.begin(), searchvec.end())!= vec.end();}int main(){
std::vector<int> v ={2,4,6,8};//THIS WORKS. SEARCHING ONLY ONE ELEMENT.
std::vector<int> searchVector1 ={2};if(search_vector(v,searchVector1))
std::cout<<"searchVector1 found"<<std::endl;else
std::cout<<"searchVector1 not found"<<std::endl;//THIS WORKS, AS THE ELEMENTS ARE SEQUENTIAL.
std::vector<int> searchVector2 ={6,8};if(search_vector(v,searchVector2))
std::cout<<"searchVector2 found"<<std::endl;else
std::cout<<"searchVector2 not found"<<std::endl;//THIS WILL NOT WORK, AS THE ELEMENTS ARE NOT SEQUENTIAL.
std::vector<int> searchVector3 ={8,6};if(search_vector(v,searchVector3))
std::cout<<"searchVector3 found"<<std::endl;else
std::cout<<"searchVector3 not found"<<std::endl;}
Também há flexibilidade de passar alguns algoritmos de busca. Consulte aqui.
Pessoalmente, usei modelos tarde para lidar com vários tipos de contêineres de uma só vez, em vez de lidar apenas com vetores. Encontrei um exemplo semelhante on-line (não me lembro de onde), então o crédito é para quem quer que tenha roubado isso. Esse padrão específico parece lidar com matrizes brutas também.
template<typenameContainer,typename T =typename std::decay<decltype(*std::begin(std::declval<Container>()))>::type>bool contains(Container&& c, T v){return std::find(std::begin(c), std::end(c), v)!= std::end(c);}
Respostas:
Você pode usar
std::find
em<algorithm>
:Isso retorna um bool (
true
se presente,false
caso contrário). Com o seu exemplo:fonte
#include <algorithm>
ou então você pode obter erros muito estranhos como 'não consegue encontrar função correspondente no std namespace'.find()
ainda não é uma função membrostd::vector
, como seria de esperar? Eu me pergunto se isso é de alguma forma uma conseqüência do modelo.std::vector<>::find()
não daria nenhuma vantagem, nem é necessário; portanto, não, não deve ser um membro. Veja também en.wikipedia.org/wiki/Coupling_%28computer_programming%29mvec.find(key) != mvec.cend()
é preferívelstd::find(mvec.cbegin(), mvec.cend(), key) != mvec.cend()
.Como outros já disseram, use o STL
find
oufind_if
funções. Mas se você está procurando em grandes vetores e isso afeta o desempenho, você pode querer classificar seu vetor e use asbinary_search
,lower_bound
ouupper_bound
algoritmos.fonte
Use find do cabeçalho do algoritmo de stl. Ilustrei seu uso com o tipo int. Você pode usar qualquer tipo que quiser, desde que possa comparar a igualdade (sobrecarga == se for necessário para sua classe personalizada).
fonte
Se seu vetor não for solicitado, use a abordagem sugerida pelo MSN:
Se seu vetor for encomendado, use o método binary_search sugerido por Brian Neal:
a pesquisa binária produz O (log n) pior desempenho, o que é muito mais eficiente que a primeira abordagem. Para usar a pesquisa binária, você pode usar qsort para classificar o vetor primeiro e garantir que ele seja ordenado.
fonte
std::sort
?qsort
é muito ineficiente em vetores .... ver: stackoverflow.com/questions/12308243/...Eu uso algo assim ...
... dessa forma, é realmente claro e legível. (Obviamente, você pode reutilizar o modelo em vários locais).
fonte
value_type
o contêiner para o tipo de elemento. Eu adicionei uma resposta como esta.No C ++ 11 você pode usar
any_of
. Por exemplo, se for umvector<string> v;
então:Como alternativa, use uma lambda:
fonte
bind1st
ebind2nd
foram descontinuados desde C ++ 11 e completamente removidos em C ++ 17. Usebind
complaceholders
e / ou lambdas.Aqui está uma função que funcionará para qualquer contêiner:
Observe que você pode se safar com 1 parâmetro de modelo porque pode extrair o
value_type
do Container. Você precisa dotypename
porqueContainer::value_type
é um nome dependente .fonte
Lembre-se de que, se você estiver fazendo muitas pesquisas, existem contêineres STL que são melhores para isso. Não sei qual é a sua aplicação, mas vale a pena considerar contêineres associativos como std :: map.
std :: vector é o contêiner de escolha, a menos que você tenha uma razão para outra e as pesquisas por valor possam ser essa.
fonte
Use a função de localização STL .
Lembre-se de que também existe uma função find_if , que você pode usar se sua pesquisa for mais complexa, ou seja, se você não estiver apenas procurando por um elemento, mas, por exemplo, desejar ver se há um elemento que atenda a um determinado condição, por exemplo, uma sequência que começa com "abc". (
find_if
daria a você um iterador que aponta para o primeiro elemento desse tipo).fonte
Com o boost você pode usar
any_of_equal
:fonte
Você pode tentar este código:
fonte
Você pode usar a
find
função, encontrada nostd
espaço para nome, iestd::find
. Você passa astd::find
funçãobegin
e oend
iterador do vetor que deseja pesquisar, junto com o elemento que você está procurando e compara o iterador resultante ao final do vetor para ver se eles correspondem ou não.Você também pode desreferenciar esse iterador e usá-lo normalmente, como qualquer outro iterador.
fonte
Você pode usar count também. Ele retornará o número de itens presentes em um vetor.
fonte
find
é mais rápido quecount
, porque não continua contando após a primeira partida.Se você quiser encontrar uma string em um vetor:
fonte
Outro exemplo usando operadores C ++.
fonte
fonte
(C ++ 17 e superior):
pode usar
std::search
tambémIsso também é útil para pesquisar a sequência de elementos.
Também há flexibilidade de passar alguns algoritmos de busca. Consulte aqui.
https://en.cppreference.com/w/cpp/algorithm/search
fonte
Pessoalmente, usei modelos tarde para lidar com vários tipos de contêineres de uma só vez, em vez de lidar apenas com vetores. Encontrei um exemplo semelhante on-line (não me lembro de onde), então o crédito é para quem quer que tenha roubado isso. Esse padrão específico parece lidar com matrizes brutas também.
fonte
Usando o Newton C ++ , é mais fácil, auto-documentado e mais rápido do que com o std :: find devido ao retorno de um bool diretamente.
Eu acho que é óbvio o que as funções fazem.
fonte