【问题标题】:How to search for an element in an stl list?如何在 stl 列表中搜索元素?
【发布时间】:2011-06-03 23:58:21
【问题描述】:

列表中是否有 find() 函数,就像向量中的函数一样?

有没有办法在列表中做到这一点?

【问题讨论】:

  • std::vector 有一个find() 方法?这对我来说是个新闻。
  • mybad... 我的意思是 fint(vectoriterator.begin(),vectoriterator.end(),string)
  • 你是对的,std::vector 没有find() 方法。
  • @Marc:二分查找需要随机访问,而列表是不允许的(我们这里说的是 STL 列表,所以它是一个链表,而不是像 ArrayList 之类的东西)
  • @Marc:实际上,对于复杂的operator<,分支成本比内存访问成本相形见绌。

标签: c++ stl


【解决方案1】:

您使用来自<algorithm>std::find,它同样适用于std::liststd::vectorstd::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

【讨论】:

  • std::find() 的时间复杂度是多少?也许,O(n)?
  • 排序容器没有二进制搜索功能?延迟实现。
  • @LDS - std::binary_search 提供二分搜索。
  • string 具有查找系列功能。不确定其他容器没有。
  • std::binary_search 仅返回 truefalse。我认为 OP 可能对LB = std::lower_bound(v.begin(),v.end(),value) 感兴趣。然后LB 是第一个元素的迭代器 >= 我们寻找的value。如果是*LB==value,那么LB - v.begin()value的索引。
【解决方案2】:

不,不是直接在std::list 模板本身中。但是,您可以像这样使用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】:

    除了使用std::find(来自算法)之外,您还可以使用std::find_if(即IMO,优于std::find)或来自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;
        }
    }
    

    【讨论】:

    • 为什么 find_if 更好?如果您正在搜索与相等匹配的元素,您是说您不会使用 find 而是使用 find_if 吗? find_if 确实允许您自定义搜索,但如果您必须使用一些可怕的仿函数来搜索 equals,与使用 find 相比,它会使代码看起来非常难看。
    • @CashCow 这一切都取决于向量或列表中的元素类型。有时无法使用 std::find。
    • 是的,有时您需要 find_if 这就是为什么它是库的一部分,但这并不能使它“更好”,即使在 std::find 工作时您也可以使用它。
    • +1 如果你已经有一个一元谓词,find_if 更好。
    • 也许你应该添加一个小例子来展示优势
    【解决方案4】:

    你能做什么和你应该做什么是不同的事情。

    如果列表很短,或者您只需要调用一次 find ,则使用上面的线性方法。

    然而,线性搜索是我在慢代码中发现的最大弊端之一,并考虑使用有序集合(如果允许重复,则为集合或多重集合)。如果您出于其他原因需要保留列表,例如使用 LRU 技术,或者您需要维护插入顺序或其他顺序,请为其创建索引。您实际上可以使用列表迭代器(或多重集)的 std::set 来做到这一点,尽管您需要在修改列表时随时维护这一点。

    【讨论】:

      【解决方案5】:

      不,find() 方法不是std::list 的成员。 而是使用&lt;algorithm&gt;中的std::find

          std :: list < int > l;
          std :: list < int > :: iterator pos;
      
          l.push_back(1);
          l.push_back(2);
          l.push_back(3);
          l.push_back(4);
          l.push_back(5);
          l.push_back(6);
      
          int elem = 3;   
          pos = find(l.begin() , l.end() , elem);
          if(pos != l.end() )
              std :: cout << "Element is present. "<<std :: endl;
          else
              std :: cout << "Element is not present. "<<std :: endl;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-10
        • 1970-01-01
        • 2016-02-11
        • 1970-01-01
        相关资源
        最近更新 更多