【问题标题】:Most efficient way to search array of string objects in c++?在 C++ 中搜索字符串对象数组的最有效方法?
【发布时间】:2014-05-24 13:02:47
【问题描述】:

我一直在寻找有关此主题的更多信息,但似乎找不到我正在寻找的答案,所以希望您能提供帮助!

我正在处理的部分任务是编写一个程序来搜索字符串数组(地址簿),如果找到完全或部分匹配项,则返回匹配项。我可以使用 C 字符串数组轻松完成此操作,strstr() 函数通过 for 循环运行,并将指针设置为将用户输入关键字运行到数组中的结果(见下文)。

我的问题是,如果有的话,我将如何利用 String 对象来做到这一点?我还需要考虑到不止一种可能的匹配。这也是执行该程序的最有效方法吗?我已经提交了我的工作版本,我只是好奇其他一些方法可以完成同样的任务!

#include <iostream>
#include <cstring>
using namespace std;

int main()
{

  bool isFound = false;         // Flag to indicate whether contact is found
  const int SIZE = 11;          // Size of contacts array
  const int MAX = 50;           // Maximum characters per row
  char contacts[SIZE][MAX] = { 
                                "Jig Sawyer, 555-1223",
                                "Michael Meyers, 555-0097",
                                "Jason Vorhees, 555-8787",
                                "Norman Bates, 555-1212",
                                "Count Dracula, 555-8878",
                                "Samara Moran, 555-0998",
                                "Hannibal Lector, 555-8712",
                                "Freddy Krueger, 555-7676",
                                "Leather Face, 555-9037",
                                "George H Bush, 555-4939",
                                "George W Bush, 555-2783"
                              };
  char *ptr = NULL;             // Pointer to search string within contacts
  char input[MAX];              // User search input string


  // Get the user input
  cout << "Please enter a contact to lookup in the address book: ";
  cin.getline(input,MAX);

  // Lookup contact(s)
  for (int i=0; i<SIZE; i++)
  {
    ptr = strstr(contacts[i], input);
    if (ptr != NULL)
      {
        cout << contacts[i] << endl;
        isFound = true;
      }
  }

  // Display error message if no matches found
  if (!contactFound)
    cout << "No contacts found." << endl;

  return 0;
} 

如你所知,我喜欢恐怖片 :)

【问题讨论】:

  • My question is, how would I be able to do this, if at all, utilizing String objects?首先问问自己可以使用什么算法或数据结构来进行高效搜索。无论您是否使用字符串都不应该在这个初始点发挥作用。
  • 我不确定它是否有预制函数,但 boost::adaptors::filtered 带有一个短 lambda 使得这很容易。
  • 啊,没提-第二学期的CS学生。下学期的数据结构和算法。我使用 C-String 方法只是因为我在进入 C++ 之前学习了一些 C。显然这是一个非常小的列表,但如果我有 10K 条记录,我想走最有效的路线。
  • @bran.io 保持记录按名称排序然后进行二分搜索怎么样?
  • @bran.io - “下学期的数据结构和算法” - 听起来像是找到最有效的方法来徒手在大海捞针。甚至二分搜索也不行(正如 faranwath 建议的那样)?

标签: c++ arrays string search cstring


【解决方案1】:

您确实需要将每个字符串分解为可排序的组件。如果您还不了解结构,可以使用更多数组。这将允许您构建可以加快搜索速度的“索引”表。

最有效的方法取决于数据的数量和数据的组织。

对于小型数据集,不同搜索方法之间的时间差异通常可以忽略不计——程序中的某些其他项目需要更长的时间(例如输入或输出)。

对于字符串数据,大部分时间都花在将一个字符串的每个字符与另一个字符串进行比较。其他操作,例如移动索引,可以忽略不计。

由于已经进行了搜索方法之间的比较,请在网上搜索“性能字符串搜索比较”。

【讨论】:

    【解决方案2】:

    另一种方法是使用正则表达式进行字符串搜索。现在有a lot of info out there,我将提供一个简单的示例,您尝试将记录(地址)的子范围与word2Search(我已对其进行硬编码以避免混淆示例)进行匹配。

    我还使用(cmets 中已经提到的一种技术)对数组进行排序的预处理步骤。注意两件事:

    • 排序是为了实现快速搜索方法,即二分查找(这里用lower_boundupper_bound实现)

    • 如果您要搜索的单词不在记录的开头,则对记录进行排序没有意义,因为您将无法找到有效范围(此处为itite)搜索(例如,如果您搜索数字,字符串的排序将在字符串之间的字典比较中完成,因此在以 M J 和以此类推)

    cmets 中的解释:

    int main()
    {
        // 1. Minor change - an array of strings is used
        string contacts[] = { 
            "Jig Sawyer, 555-1223",
            "Michael Meyers, 555-0097",
            "Jason Vorhees, 555-8787",
            "Norman Bates, 555-1212",
            "Count Dracula, 555-8878",
            "Samara Moran, 555-0998",
            "Hannibal Lector, 555-8712",
            "Freddy Krueger, 555-7676",
            "Leather Face, 555-9037",
            "George H Bush, 555-4939",
            "George W Bush, 555-2783"
        };
        // 2. The array is sorted to allow for binary search
        sort(begin(contacts), end(contacts));
        // 3. Example hard coded a word to search 
        string word2Search = "George";
        // 4. A regular expression is formed out of the target word
        regex expr(word2Search);
        // 5. Upper and lower bounds are set for the search
        char f = word2Search[0];
        std::string val1(1, f);
        std::string val2(1, ++f);
        // 6. Perform the search using regular expressions
        for (auto it(lower_bound(begin(contacts), end(contacts), val1)), 
            ite(lower_bound(begin(contacts), end(contacts), val2)); it != ite; ++it)
        {
            if (regex_search(it->begin(), it->end(), expr)) {
                cout << *it << endl;
            }
        }
    
        return 0;
    }
    

    【讨论】:

    • 非常感谢 Nikos,并提供了如此清晰的示例。我在 ruby​​ 中学习正则表达式,但我当然可以将其应用于 C++。与使用诸如 C/C++ 之类的主力语言所拥有的所有灵活性相比,看到您可以毫不费力地使用这些新语言之一解决问题的方式令人着迷。
    猜你喜欢
    • 2012-12-18
    • 2012-03-23
    • 1970-01-01
    • 2016-11-22
    • 2014-04-02
    • 2012-04-30
    • 1970-01-01
    • 2021-08-20
    • 2010-10-25
    相关资源
    最近更新 更多