【问题标题】:binary search with vectors in c++在 C++ 中使用向量进行二进制搜索
【发布时间】:2013-03-30 19:07:10
【问题描述】:

我正在为大学作业编写二进制搜索方法,虽然我觉得这是正确的做法,但我觉得运行时间比它应该的要长.. 有人看到这有什么错误吗? iterator 是一个自定义类,没有什么花哨的,可以满足您的期望。 vec 是一个迭代器向量,它指向一个更大的链接列表,其中包含我“真正”搜索的内容

iterator searchVec(const I& item)
{
    int left = 0;
    int right = (int)vec.size()-1;
    int mid = (right+left)/2;

    while(*vec.at(left) != *vec.at(right)){
        mid = (right+left)/2;
        if (mid == 0 || mid == vec.size()-1){
            //nothign else to search, we didnt find anything
            return *vec.end();
        }
        if (*vec.at(mid) == item){
            return vec.at(mid);
        }
        else if (item > *vec.at(mid)){
            left = mid;
        }
        else if (item < *vec.at(mid)){
            right = mid;
        }
    }
    return vec.at(mid);
}

【问题讨论】:

  • 您不能取消引用 vec.end()。你也不应该,因为你想返回一个 iterator,而不是一个值。
  • 好点,我修改为return vec.at(vec.size()-1);
  • 显而易见,您确定您的向量已排序(并且该排序使用对取消引用值的比较),对吗?此外,您将永远找不到第一个或最后一个迭代器指向的项目,因为您在if (*vec.at(mid) == item) 之前测试了if (mid == 0 || mid == vec.size()-1)。你不需要第一次检查,你应该删除它。
  • 那如果向量是空的呢?不,返回一个迭代器通常是一个好主意,您只需要正确处理所有细节。
  • vector.at() 不返回迭代器。你为什么要取消引用它?这是指向类型 I 的指针向量吗?

标签: c++ algorithm binary-search


【解决方案1】:

一些想法:

  • 您使用的是std::vector::at,即slow compared to std::vector::operator[]
  • 您不能取消引用vec.end()。通常,如果您想向调用者发出未找到任何项目的信号,则会返回它。但是在这里,由于您没有返回 vec 的迭代器,因此您可能应该使用布尔输出参数或异常来发出信号。
  • 循环条件在我看来不正确。似乎应该是left &lt;= right 而不是*vec[left] != *vec[right]。然后循环的目的是选择项目。如果我们跳出循环,则找不到任何项目。
  • 退出条件是无用的,并且会阻止找到第一个和最后一个元素,如 cmets 中所述。

        if (mid == 0 || mid == vec.size()-1)
            //nothign else to search, we didnt find anything
            return *vec.end();
        }
    

这是一个稍微更正的代码:

iterator searchVec(const I& item)
{
    int left = 0;
    int right = (int)vec.size()-1;
    int mid = (right+left)/2;

    while(left <= right) // corrected condition
    {
        mid = (right+left)/2;
        iterator it = vec[mid]; // avoid recomputing vec[mid]
        if (*it == item) // this can be moved in a else {} statement,
            return it;   // after the else if (no impact on performances I think)
        else if (item > *it)
            left = mid + 1; // you were not strictly decreasing the interval
        else if (item < *it)
            right = mid - 1; // same here
    }
    throw not_found();
}

【讨论】:

    猜你喜欢
    • 2020-12-16
    • 1970-01-01
    • 2015-10-31
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多