用于范围搜索的数据结构是什么?

时间:2012-03-20 15:15:14

标签: c++ algorithm stl

尝试制作一个简单的程序来编目书籍。像这样的东西,例如:

struct book{
    string author;
    string title;
    int catalogNumber;
}

最终,我希望能够根据范围进行标题搜索。因此,用户可以指定显示书籍的结果,其中标题以“aa”开头,但是“be”。理想情况下,搜索平均情况是对数的。

STL中有什么东西可以帮助我吗?否则,最好的方法是什么?

谢谢!

3 个答案:

答案 0 :(得分:4)

您可以将它们存储在std::set中,并使用std::lower_boundstd::upper_bound来查找范围(是的,这应该是对数的)。为此,您需要定义operator<以仅对您关注的字段进行操作(在这种情况下为title)。

如果您(实际上)始终将标题视为关键字,您可能更愿意使用std::map<std::string, info>info定义为:

struct info { 
     string author;
     int catalogNumber;

     info(string a, int c) : author(a), catalogNumber(c) {}
};

这使得一些操作更容易,例如:

books["Moby Dick"] = info("Herman Melville", 1234);

如果您想支持按标题或作者搜索(例如),请考虑使用Boost bimapmulti_index之类的内容。

对于它的价值,我还要认真地想到使用string而不是int作为目录号。标准编号系统(例如,杜威十进制,国会图书馆,ISBN)几乎都不会很好地存储在一个整数中。

答案 1 :(得分:1)

您可以将元素放在std::set中。问题在于,您可能希望您的用户能够按标题和作者进行搜索。解决方案只是维护两组,但如果您的数据发生变化,维护起来可能会很棘手,而且您需要两倍的空间。

您总是可以编写类似Trie的内容,但很可能您的数据会发生变化,并且维持对数搜索时间变得更加困难。您可以实现任何类型的Self-balancing binary search tree,但这基本上是set - Red-black tree。写一个不是最简单的任务,但是......

更新:您可以散列所有内容并实现某种形式的Rabin-Karp string search algorithm,但是您应该知道如果您这样做可能会发生冲突。您可以通过双重散列和/或使用良好的散列函数来降低其概率。

答案 2 :(得分:1)

您可以使用trie [在此扩展@smarinov建议]:

在trie中查找具有公共前缀的相关单词集非常容易,只需按照trie中的指针,直到到达表示所需公共前缀的节点。此节点是包含所需公共前缀的trie。

在您的示例中,您将需要:

range("aa","be") = prefix("a") + (prefix("b[a-e]")

此OP的预期复杂度为O(|S|),其中|S|是公共前缀的长度。请注意,任何算法都不会比[O(logn)算法实际上O(|S| * logn)更好,因为比较操作取决于字符串的长度。