【问题标题】:How can I do a binary search on a part of the keys in a std::map?如何对 std::map 中的部分键进行二进制搜索?
【发布时间】:2014-04-16 22:59:55
【问题描述】:

我有一张数据地图;关键是std::string。我想对它进行二分查找,但我不能只使用std::map::find(),因为我只会提供一部分密钥。

假设我有一张包含以下键的地图:

["abc"] -> ...
["efg"] -> ...
["ijk"] -> ...
["iik"] -> ...

我想通过这个搜索,假设只提供"i",搜索应该返回:

["ijk"] -> ..., ["iik"] -> ...

这可能吗?我曾尝试使用迭代器来执行此操作,但失败了,因为我不能将它们视为索引。

注意:由于其他原因,我将数据保存在地图中,因此我不想将其更改为不同的数据结构。

【问题讨论】:

  • 像往常一样,通过一个小代码示例展示您实际尝试过的内容!

标签: c++ c++11 dictionary containers binary-search


【解决方案1】:

这是可能的,但您实际上不需要对数据进行二进制搜索。

您可以使用lower_bound 查找第一个元素,然后推进生成的迭代器,直到您的键不再符合您的条件,将它们存储在<vector> 或类似容器中以将它们全部返回。

【讨论】:

  • lower_bound 是二分搜索 :)
  • 我想把二分搜索看作是一个实现细节:)
  • 好的,从技术上讲,“二分搜索”这个词不在标准中;我会给你那个。但考虑到对该功能的要求,它真的不可能是别的。
  • 虽然std::map 通常是使用红黑(二进制)树实现的,但我看不出map 必须是二进制 树的充分理由。
  • 可能想提一下is_transparent,这可以使某些类型更高效和/或实用。
【解决方案2】:

map::lower_bound() 会在这里为您提供帮助。

【讨论】:

    【解决方案3】:

    根据lccarrascoMichael Burr 的建议,我基于map::lower_bound() 构建了一个解决方案。此函数为您要查找的地图中的第一个元素提供了一个迭代器。该函数执行二进制搜索,因为它的复杂度是对数大小。

    然后,只要您要查找的字符串是映射中值的前缀,您就必须推进提供的迭代器。 One way 这样做是使用string::compare()

    为了清楚起见,我选择了int 作为您地图的值。请用您的数据类型替换它。总而言之,代码如下:

    int main() {
        std::map <std::string, int> myMap{ {"abc", 1}, {"efg", 2}, {"ijk", 3}, {"iik", 4} };
        std::string prefix("i");
    
        for (auto it = myMap.lower_bound(prefix); it != std::end(myMap) && it->first.compare(0, prefix.size(), prefix) == 0; ++it)
            std::cout << it->first << " -> " << it->second << std::endl;
    
        return 0;
    }
    

    输出:

    iik -> 4
    ijk -> 3

    Code on Ideone

    【讨论】:

      猜你喜欢
      • 2023-03-29
      • 1970-01-01
      • 2017-02-10
      • 2019-02-08
      • 2014-01-04
      • 2015-03-30
      • 1970-01-01
      • 2016-08-04
      • 2010-11-01
      相关资源
      最近更新 更多