如何解决带有相反顺序的集合上的std :: lower_bound
说我有一个std::set<int>
,我想用两种方式执行lower_bound(x)
操作。也就是说,
- 使第一个元素大于或等于
x
- 获取最后一个小于或等于
x
的元素
使用std::vector
,我可以使用一个排序的vector
std::vector<int> v({1,2,3,5,6});
sort(v.begin(),v.end());
auto a = std::lower_bound(v.begin(),v.end(),4); // gives 5
auto b = std::lower_bound(v.rbegin(),v.rend(),4,greater<int>()); // gives 3
我可以使用std::set
做类似的事情,还是必须维护一个附加的set
,它们具有相同的值但使用了反向比较器?
解决方法
我可以对
std::set
做些类似的事情
是的,std::set<int>
总是按std::less<int>
的顺序进行,而反向迭代器则按std::greater<int>
的顺序进行。
std::set<int> v({1,2,3,5,6});
auto a = std::lower_bound(v.begin(),v.end(),4); // 5
auto b = std::lower_bound(v.rbegin(),v.rend(),4,std::greater<int>()); // 3
如果您的设备具有自定义比较器,则可以执行类似的操作
template<typename Compare>
class reverse_compare {
Compare comp;
bool operator()(auto lhs,auto rhs) {
return comp(rhs,lhs);
}
}
,
std::set
包含唯一值,因此要获得“ 小于x
的最后一个元素”,只需使用set::lower_bound
来获得第一个迭代器元素>= x
,然后递减。然后,通过简单的if-check,解决方案可以扩展为支持值<= x
。
类似这样的东西:
int main() {
std::set<int> v({ 1,6 });
int x = 4;
auto a = v.lower_bound(x);
if (a == v.end()) return 1; // handle the not-found case ...
auto b = a; // b "points" to the element >= x
if (*a != x) {
a--; // a now "points" to the element <= x
if (a == v.end()) return 1; // handle the not-found case ...
}
std::cout << *a << "," << *b << "\n"; // prints 3,5
}
,
基于rustyx的答案,这是一个更优雅的实现:
using namespace std;
template<typename T>
typename set<T>::reverse_iterator rlower_bound(set<T>& s,const T x) {
if(s.empty()) return s.rend();
auto it = s.upper_bound(x);
return make_reverse_iterator(it);
}
template<typename T>
typename set<T>::reverse_iterator rupper_bound(set<T>& s,const T x) {
if(s.empty()) return s.rend();
auto it = s.lower_bound(x);
return make_reverse_iterator(it);
}
int main() {
set<int> s({1,6});
int x = 4;
cout << *s.lower_bound(x) << endl;
cout << *rlower_bound(s,x) << endl;
}
此外,这与我的向量示例一致,在执行反向reverse_iterator
时您得到一个lower_bound
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。