我如何(c++ STL)二进制搜索抽象类

How do I (C++ STL) binary_search for Abstract classes?

本文关键字:二进制 搜索 抽象类 STL c++      更新时间:2023-10-16

可以使用STL二进制搜索算法(binary_search, upper_bound, lower_bound)在基指针向量中搜索派生对象,如下所示。由于Base是抽象的(受保护的构造函数),因此必须为搜索函数实例化派生对象,这有点难看。

我想搜索给定时间以上的第一个派生向量。我能做到这一点,而不随意选择和实例化我的许多继承类之一吗?

#include <algorithm>
#include <vector>
#include <stdio.h>
using namespace std;
class Base {
protected:
  Base(double t, int d) : data(d), time(t) {}
public:
  double time;
  int data;
  virtual void print() { 
    printf("Base: data = %d, time = %.1fn",data,time); 
  }
};
class Derived : public Base {
public:
  Derived(double t, int d) : Base(t,d) {}
  virtual void print() { 
    printf("Derived: data=%d, time=%.1fn",data,time);
  }
};
struct BaseTimeComp {
  bool operator()(Base* a, Base* b) { return a->time < b->time; }
};
int main()
{
  vector<Base*> v;
  for(int i=0; i<5; i++) { v.push_back(new Derived(i+0.4,i)); }
  Base* pLow = *(lower_bound(v.begin(),v.end(),
                             new Derived(3.5,0), //NOT "new Base(3.5,0)"
                             BaseTimeComp()));
  printf("lower bound for time=3.5:n");
  pLow->print();
}

程序打印:时间下界=3.5:导出:data=4, time=4.4

比较的对象不必与容器的内容类型相同,它只需要是可以与容器进行比较的对象:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    int i = *(lower_bound(v.begin(), v.end(), 1.5));  // <<< NOTE: floating point "value"
    cout << i << endl;
}

你必须制造某种Base的假设是错误的。你可以定义一个适合你的比较的BaseKey,只要你的显式(或隐含)比较运算符知道要做什么。

下面的注释也是错误的,正如下面这个更复杂的例子所示:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct A {
    int x;
    A(int _x) :x(_x) { }
    bool operator < (double d) { return x < d; }
};
int main()
{
    vector<A> v;
    v.push_back(A(1));
    v.push_back(A(2));
    v.push_back(A(3));
    int i = (lower_bound(v.begin(), v.end(), 1.5))->x;
    cout << i << endl;
}

您还可以显式地使用比较类型(这有助于解决操作顺序问题,例如您可能在upper_bound中发现的问题):

class CompareADouble {
public:
    bool operator () (const double d, A& a) { return d < a.x; }
};
int main()
{
    vector<A> v;
    v.push_back(A(1));
    v.push_back(A(2));
    v.push_back(A(3));
    int i = (upper_bound(v.begin(), v.end(), 1.5, CompareADouble()))->x;
    cout << i << endl;
}

提供多态性比较的binary_search示例:

class CompareADouble {
public:
    bool operator () (const double d, A& a) { return d < a.x; }
    bool operator () (A& a, const double d) { return a.x < d; }
};
...
    bool exists = binary_search(v.begin(), v.end(), 1.5, CompareADouble());
    cout << exists << endl; // false
    exists = binary_search(v.begin(), v.end(), 1.0, CompareADouble());
    cout << exists << endl; // true because 1.0 < 1 == false && 1 < 1.0 == false

您可以传递一个空指针,并设计比较函数忽略它,只测试另一个对象的特定属性

在某种程度上,可以通过使用静态方法:

class Base {
...
public:
  static Base *newSearchInstance(double t, int d) {return new Base(t,d);};
...
};

和调用LowerBound:

Base* pLow = *(lower_bound(v.begin(),v.end(),
                         Base::newSearchInstance(3.5,0), //<------
                         BaseTimeComp()));

这意味着您不需要了解任何派生类,但是获得Base的实例从一开始就违背了Base是抽象的目的