如何以特定方式在 c++ STL 中查找

How to find in c++ STL in a specific manner?

本文关键字:c++ STL 查找 方式      更新时间:2023-10-16
map< pair<int,int> , int > m ;

在这里,pair.firstpair.second是积极和pair.second >= pair.first.

我想在 map m 中找到所有迭代器,以便为给定键。键是位于对之间的整数.key例如 2 和 对是 [2,5][1,2] 等。
例如 m[1,3] = 10 , m[3,5] = 6 , m[1,8] = 9 , m[7,8] = 15然后当我搜索m.find(3)时,它会返回m[1,3]m[1,8]m[3,5]的迭代器。如果没有密钥,那么它将返回m.end()

我不确定你为什么要这样做,但这些天提升间隔容器库非常强大。

假设您可能想要跟踪特定点的映射值的总和,您可以简单地将拆分组合样式应用于输入数据和利润:

住在科里鲁

#include <boost/icl/split_interval_map.hpp>
#include <boost/range/iterator_range.hpp>
#include <iostream>
namespace icl = boost::icl;
int main() {
    using Map  = icl::split_interval_map<int, int>;
    using Ival = Map::interval_type;
    Map m;
    m.add({Ival::closed(1,3), 10});
    m.add({Ival::closed(3,5), 6});
    m.add({Ival::closed(1,8), 9});
    m.add({Ival::closed(7,8), 15});
    for (auto e : m) std::cout << e.first << " -> " << e.second << "n";
    std::cout << "------------------------------n";
    for (auto e : boost::make_iterator_range(m.equal_range(Ival::closed(3,3))))
        std::cout << e.first << " -> " << e.second << "n";
}

这将告诉我们:

[1,3) -> 19
[3,3] -> 25
(3,5] -> 15
(5,7) -> 9
[7,8] -> 24
------------------------------
[3,3] -> 25

注意如何

  • 合并非常准确地反映了[3,3]是唯一一个同时与输入数据的[1,3][3,5]重合的点,因此,我们在组合集合中得到半开区间([1,3)[3,3](3,5](。
  • 另请注意,对这一个点的查询如何正确返回您感兴趣的所有三个间隔的10+6+9总和。

这有什么用?

所以,你看我把问题的焦点从"怎么做?"转移到了"什么?"。它通常有助于陈述代码的目标而不是特定的机制。

当然,如果您对平均值、最小值或最大值感兴趣的不是总和,您可能会发现自己在编写一些自定义的组合策略。

奖金 如果您愿意,以下是您至少可以使用 Boost Icl:Live On Coliru 编写 OP 中提出的问题的解决方案的方法。虽然它不是特别高效,但它是直接和强大的。

我认为您可以存储(和使用(映射的相应键,而不是迭代器。如果是这样,那么代码可能看起来像

#include <iostream>
#include <map>
#include <algorithm>
#include <vector>
#include <utility>
int main() 
{
    std::map<std::pair<int, int>, int> m;
    m[{ 1, 3}] = 10; 
    m[{ 3, 5}] = 6;
    m[{ 7, 8}] = 15;
    typedef std::map<std::pair<int, int>, int>::value_type value_type;
    typedef std::map<std::pair<int, int>, int>::key_type key_type;
    int search;
    auto in_range = [&search]( const value_type &value )
    {
        return value.first.first <= search && search <= value.first.second; 
    };
    search = 3;
    std::vector<key_type> v;
    v.reserve( std::count_if( m.begin(), m.end(), in_range ) );
    for ( const auto &p : m )
    {
        if ( in_range( p ) ) v.push_back( p.first );
    }
    for ( const auto &p : v ) 
    {
        std::cout << "[ " << p.first << ", " << p.second << " ]" << std::endl;
    }
    return 0;
}

输出为

[ 1, 3 ]
[ 3, 5 ]

考虑到 key.first 小于或等于 key.second,其中 key 是映射的键。

没有办法避免从地图的开头进行线性搜索,因为如果第一个元素是 {0,INT_MAX},那么它匹配并且你想要的元素不一定在连续的范围内,例如,如果你有 {1,3},{2,2}{3,5},你只需要键为 3 时的第一个和最后一个元素。

当您到达first大于键的元素时,可以停止搜索。

像这样的东西(未经测试(:

typedef map< pair<int,int> , int > Map;
std::vector<Map::iterator>
find(int key, const Map& m)
{
  std::vector<Map::iterator> matches;
  for (Map::iterator it = m.begin(), end = m.end(); it != end && key <= it->first; ++it)
  {
    if (it.first >= key && key <= it.second)
      matches.push_back(it);
  }
  return matches;
}

你可以把它变成一个函子并使用find_if但我不确定它是否值得。

如果只想每次调用返回一个迭代器:

typedef map< pair<int,int> , int > Map;
Map::iterator
find(int key, const Map& m, Map::iterator it)
{
  for (Map::iterator end = m.end(); it != end && key <= it->first; ++it)
  {
    if (it.first >= key && key <= it.second)
      return it;
  }
  return m.end();
}
Map::iterator
find(int key, const Map& m)
{ return find(key, m, m.begin()); }

如果你只需要一个迭代器到映射中找到的下一个值,你可以使用 std::find_if 算法,如下所示:

int key=2;
map<pair<int,int>, int>::iterator it =std::find_if(m.begin(),m.end(),
                         [key](pair<pair<int,int>,int> entry)
                         {
                           return (entry.first.first <= key) 
                                  && (entry.first.second >= key);
                         }
                         );
cout << "the next value is: [" << it->first.first << "/";
cout << it->first.second << "] " << it->second << endl;