使用二分搜索

时间:2015-04-29 10:49:27

标签: c++ vector task binary-search

我目前正在做作业,我差不多完成了,但我似乎并不完全理解我的任务的最后部分。这是任务描述,粗体文字是我不明白的地方:

  

编写一个保留预约簿的程序。创建一个类约会,用于存储约会,约会日,开始时间和结束时间的描述。您的程序应将约会保留在已排序的向量中。用户可以添加约会并打印出给定日期的所有约会。 添加新约会时,使用二进制搜索查找应在向量中插入的位置。如果与其他约会发生冲突,请不要添加。

我上周刚刚学习了线性/二进制搜索算法,现在我无法看到我应该在这里做些什么。通过二进制搜索,我可以在一个内部找到一个值,例如vector(就像我的情况一样),对吧?那么如何确定我应该在向量中插入新添加的约会?应该告诉我应该在哪里插入?我也有点困惑,我必须使用二进制搜索来查找必须插入约会的位置,即使向量可能还没有元素。它首先说"当一个约会被添加"然后它还说" ..找到它应该插入的位置",这与我的解决方案有点冲突,因为我将新添加的约会推回向量,但描述要求我先找到它的位置应该添加然后插入。听起来令人困惑,但我现在无法更好地制定它。

我不是要求直接代码,这就是为什么到目前为止我还没有发布我的解决方案。我只想澄清一下我应该对二进制搜索做些什么。感谢

3 个答案:

答案 0 :(得分:1)

Binary search用于搜索平均复杂度为O(log n)的排序数据。在std::vector中,您可以使用insert()方法在所需位置显式插入值(只要它有效)。

现在,关于你的任务:

  

添加新约会时,使用二进制搜索查找应在向量中插入的位置。如果它与另一个约会冲突,请不要添加它。

一般方法是:

struct Appointment
{
    Date date;
    Time begin;
    Time end;
    //other required members
};

现在,这本书本身:

class AppointmentsBook
{
private:
    typedef std::vector<Appointment> ApVec;

    ApVec _appointments;

public:
    //constructors, finding methods etc.
    bool add(const Appointment& ap);
};

bool AppointmentsBook::add(const Appointment& ap)
{
    ApVec::iterator pos = this->find_insert_position(ap); //find_insert_position implements searching using binary search algo

    if((pos != this->_appointments.end()) && (ap->date == pos->date) && intersects(ap.begin, ap.end, pos->begin, pos->end))
    {
        return false;
    }
    else
    {
        this->_appointments.insert(pos, ap);
        return true;
    }
}

这当然是伪代码。 intersects()函数应检查两个时间范围是否相互冲突。

请注意,如果您允许使用std库中的某些功能,则可以使用std::lower_bound,它使用二进制搜索并要求元素部分排序:

  

范围[first,last]必须至少部分排序,即根据表达式element < valuecomp(element, value)进行分区。

哦,还有一件事:如果你想知道,为什么add()内的条件会检查:

`if(pos != this->_appointments.end())`

对于空书(因此,空_appointments向量),find_insert_position()应该返回this->_appointments.end(),表示还没有约会。然后,可以(并且应该!)省略其他检查,并在向量的末尾插入新约会。

使用std::lower_bound,您的find_insert_position()功能可能如下所示:

AppointmentsBook::ApVec::iterator AppointmentsBook::find_insert_position(const Appointment& ap)
{
    if(this->_appointments.empty())
        return this->_appointments.end();

    return std::lower_bound(this->_appointments.begin(), this->_appointments.end(), ap);
}

答案 1 :(得分:0)

如果允许使用标准库算法,std :: lower_bound将执行二进制搜索,并在向量内返回要插入的新元素的位置。 在插入之前,您可以检查该位置(如果它没有指向结束())以查看是否已经同时预约。

有关lower_bound及其功能的更多信息,请参阅this link

答案 2 :(得分:0)

您必须在每个新约会上重新排序条目向量,因此向量索引表示约会顺序。如果新约会在其他约会开始和结束时间之间有开始时间,则必须保留较早的约会。

Algorithem:

  1. 在新申请之前进行二元搜索vor约会
  2. 检查碰撞
  3. 在向量中推送新的空元素
  4. 转换指数caluclatet的其他约会2
  5. 在2号
  6. 的索引计算中插入新约会