使用bsearch()获取键的多个实例

时间:2018-12-07 17:04:39

标签: c++ bsearch

有一种方法可以实现new_df = [] for i in df: for j in df.strength.dropna().drop_duplicates().tolist(): for k in i.split(): if j == k: new_df.append((i, i.replace(j, ''))) print(new_df) 来查找密钥的多个实例。

例如:bsearch()

我当前编写的代码只能找到第一个实例,并且由于其工作原理而无法继续执行第一个实例。

(obj*)bsearch(key=r,arr,elements,sizeof(obj),(int(*)(const void*, const void*)bcompare);

变量:

  • p -是指向Info类的对象的指针
  • 目标-字符的rrr
  • 列表-obj的arr
  • foundIndex -找到的元素的索引
  • 信息-从基类派生的类

**比较功能

getline(target,81);
if(strcmp(target,"exit") == 0 || strcmp(target, "") == 0) break;
p = (Info*)bsearch(target,list,num,sizeof(Info),(int(*)(const void*, const void*))bcompare);
int foundIndex = (int)(p-list);
if(!p){
    err_dis1_win();
    clrscr();
}
else{
    display_record(p);
    cout << "\n\n found at index " << foundIndex << "\n";
    getch();
    clrscr();   
}

我不能使用其他方法,例如int bcompare(char *a,Info *b){ return(strncmpi(a, b -> get_name(), strlen(a))); } 或编写自己的二进制搜索功能,而必须使用std::find

我已经尝试了else块内部的循环,并使用变量foundIndex进行了比较功能,并在循环遍历obj列表arr的返回值上使用了while循环。有没有一种方法可以从特定索引开始。感谢您的帮助。我不是在寻找代码,而是朝着正确的方向大步向前。谢谢。

注意事项-当前的代码可以按预期编译并运行,但是我自己无法确定我想要的功能。 Google和Stackoverflow上的搜索均未产生相关问题。

1 个答案:

答案 0 :(得分:2)

由于bsearch()仅返回一项,因此我将“查找键的多个实例”解释为“查找键的第一个实例”。然后,调用者可以从该项目前进到整个数组,以处理与键匹配的每个项目,直到到达末尾或到达不匹配的项目为止。

如果必须使用标准库的bsearch()函数并说服它找到与给定键匹配的第一项,那么您真正需要使用的就是您提供的比较函数。 bsearch()将根据该功能返回与键相匹配的一项,但是如果有多个项与之匹配,则不能保证将返回哪一项。然后,您必须确保只有要匹配的项目。

您可以通过适当实现比较功能来解决此问题,但是存在一个严重的问题。在某些情况下,该函数将需要评估指定给它的项之前的项目,但它不得尝试检查数组的第一个项目之前的项目。 bsearch()本身不会将有关数组范围的任何信息传达给比较函数。

至少有两种可能的解决方案,它们都不是恒星。

  1. 将数组下界存储在该函数可以访问的某个知名位置。例如,如果比较函数是静态成员函数,则可能会使用其数组的静态变量类。但这不是线程安全的。您可以对线程局部变量执行类似的操作,但是即使那样也很难看。无论哪种方式,您都必须确保在调用bsearch()之前适当地设置了该变量,这也很丑陋。

OR

  1. 确保您永远不会bsearch()进入第一项。一种可行的方法是,预先检查第一项是否匹配(但不能通过比较功能),然后如果确实匹配,则直接使用它而不是调用bsearch()。我自己将其包装在一种方法中,如果您一定不这样做,那么要求手动采用这样的调用规则也是很丑陋的。

选择了以上一项后,您可以实现一个比较功能,该功能除了查看指定项目的键之外,还查看上一项的键。遵循这些原则(假设有第二种选择):

struct my_item {
    int key;
    void *data;
};

// bsearch() passes the target item as the first argument, and the one to compare
// to it as the second
int compare_items(const void *to_find, const void *to_check) {
    const struct my_item *to_find_item = (const struct my_item *) to_find;
    const struct my_item *to_check_item = (const struct my_item *) to_check;

    // Check first how the key members are ordered
    if (to_find_item->key < to_check_item->key) {
        return -1;
    } else if (to_find_item->key > to_check_item->key) {
        return 1;
    } else {
        // The key members match, so check whether we're looking at the first
        // such item.
        const struct my_item *previous_item = to_check_item - 1;

        // If the previous item's key does match, then we know the item we're
        // looking for is an earlier one than we are presently checking.
        return (previous_item->key == to_check_item->key) ? -1 : 0;
    }
}