【问题标题】:C++ std::lower_bound() function to find insertion point for an index-sorted vectorC++ std::lower_bound() 函数查找索引排序向量的插入点
【发布时间】:2015-05-26 07:11:50
【问题描述】:

假设我有vector<Foo>,它的索引在vector<int> 中通过类Foo 中的关键字段.bar 进行外部排序。例如

class Foo {
public:
     int bar;
     int other;
     float f;
     Foo(int _b, int _o, float _f): bar(_b), other(_o), f(_f) {}
};

vector<Foo> foos;
vector<int> sortedIndex;

sortedIndex 包含foos 的排序索引。

现在,我想在foos 中插入一些内容,并在sortedIndex 中保持外部排序(排序键为.bar)。例如

foos.push_back(Foo(10,20,30.0));
sortedIndex.insert(
                   lower_bound(sortedIndex.begin(),
                               sortedIndex.end(),
                               10 /* this 10 won't work*/,
                               some_compare_function
                   ),
                   1,
                   foos.size()-1
);

显然,数字 10 不起作用:向量 sortedIndex 包含索引,而不是值,some_compare_function 会混淆,因为它不知道何时使用直接值,以及何时将索引转换为值(foo[i].bar 而不仅仅是i)在比较之前。

有什么想法吗?我已经看到了this question 的答案。答案表明我可以使用比较函数bool comp(foo a, int b)。但是,二分查找算法如何知道int b 指的是.bar 而不是.other,因为两者都定义为int

我还想知道 C++03 和 C++11 的答案是否会有所不同。请标记您的答案 C++03/C++11。谢谢。

【问题讨论】:

  • 为什么some_compare_function会混淆?它的第一个参数始终是要在foos 中查找的索引,第二个参数是bar 的值。
  • 那么,如果Foo.bar之前定义了.other,那么.other会被用作key吗?在实际示例中,我的bar 深埋在Foo...
  • .bar 的位置无关紧要。比较功能应该从任何地方获取它,请参阅我的答案。

标签: c++ sorting c++11 binary-search c++03


【解决方案1】:

some_compare_function 不会“混淆”。它的第一个参数始终是sortedIndex 的元素,第二个参数是要比较的值,在您的示例中为10。所以在 C++11 中你可以这样实现它:

sortedIndex.insert(
    lower_bound(sortedIndex.begin(),
        sortedIndex.end(),
        10,
        [&foos](int idx, int bar) {
            return foos[idx].bar < bar;
        }
    ),
    foos.size()-1
);

【讨论】:

  • 你的意思是,一般情况下,lower_bound()中的第三个参数的类型,应该与比较函数中的第二个参数一致,这样我们就可以编写不同类型的比较函数了排序向量? upper_bound() 似乎在比较函数中使用第一个参数作为“不同类型参数”,对吧?
  • @RobinHsu 是的,完全正确,除了“以便我们可以编写与排序向量不同类型的比较函数” - 我不太明白。
  • 谢谢。在 C++03 中,我只需要使用普通函数来替换您示例中的 lambda 函数。我的编译器虽然只支持 C++03..
  • 对于“以便我们可以写比较...” => 没关系,忽略它。我被排序算法中的比较函数概念给定型了,其中比较函数的两个参数应该具有相同的类型。
  • 另一个问题:我使用的是 C++03,因此没有 lambda 函数。它甚至没有 std::bind() (仅>= C++11),除非必要,我不想使用诸如boost 之类的第三方库。有没有办法在比较函数中绑定foos?我在想std::bind1ststd::bind2nd,但似乎不合适...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-27
  • 2011-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多