Std::nth_element 没有给出正确的元素
Std::nth_element is not giving the correct element
我不知道为什么在这种情况下函数 std::nth_element 没有给我正确的 X 轴中值。
为了这个测试,我创建了一个点向量:std::vector<Point> points = {Point {70, 70}, Point {50, 30}, Point {35, 45}};
函数调用是:
int median = (start + end) / 2;
Point split = get(points.begin() + start, points.begin() + median, points.begin() + end);
其中 start = 0; end = 2;
在我看来,X 轴的正确中位数是 Point(50, 30)
,而这段代码给了我 Point(70, 70)
.
下面是求中位数的代码:
template <typename Iterator>
Point get(Iterator start, Iterator median, Iterator end)
{
std::nth_element(
start,
median,
end,
[](const Point &point1, const Point &point2) {
return point1.getX() < point2.getX();
}
);
std::vector<Point>::iterator iter = median;
std::cout << *iter << std::endl;
return *iter;
}
变量 end
没有正确指向向量的末尾。因此,您只对前 2 个元素执行 nth_element()
。由于变量median
值为1,所以返回x值较大的点。
您可以使用 points.end()
而不是 points.begin() + end
。
如果你仔细阅读了CPP参考资料here中对函数的描述,你会看到:
nth_element is a partial sorting algorithm that rearranges elements in [first, last) such that: The element pointed at by nth is changed to whatever element would occur in that position if [first, last) were sorted.
对您的问题很重要的是 [first, last)
,它表示半开范围。
根据定义,half-open 范围是包含第一个元素的范围,但 NOT 最后一个元素。最后一个不包括在内。如果要包含它,则需要更进一步。在你的情况下:last+1.
所以,你只是用错误的参数调用函数。没问题。
正确的代码可能是这样的:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
struct Point {
int x{};
int y{};
int getX() const { return x; }
int getY() const { return y; }
friend std::ostream& operator << (std::ostream& os, const Point& p) {
return os << p.x << ' ' << p.y;
}
};
template <typename Iterator>
Point get(Iterator start, Iterator median, Iterator end)
{
std::nth_element(
start,
median,
end,
[](const Point& point1, const Point& point2) {
return point1.getX() < point2.getX();
}
);
std::vector<Point>::iterator iter = median;
return *iter;
}
int main() {
std::vector<Point> points = { Point {70, 70}, Point {50, 30}, Point {35, 45} };
int start = 0, end = 2;
int median = (start + end) / 2;
Point split = get(points.begin() + start, points.begin() + median, points.begin()+end+1);
std::cout << split << '\n';
}
我不知道为什么在这种情况下函数 std::nth_element 没有给我正确的 X 轴中值。
为了这个测试,我创建了一个点向量:std::vector<Point> points = {Point {70, 70}, Point {50, 30}, Point {35, 45}};
函数调用是:
int median = (start + end) / 2;
Point split = get(points.begin() + start, points.begin() + median, points.begin() + end);
其中 start = 0; end = 2;
在我看来,X 轴的正确中位数是 Point(50, 30)
,而这段代码给了我 Point(70, 70)
.
下面是求中位数的代码:
template <typename Iterator>
Point get(Iterator start, Iterator median, Iterator end)
{
std::nth_element(
start,
median,
end,
[](const Point &point1, const Point &point2) {
return point1.getX() < point2.getX();
}
);
std::vector<Point>::iterator iter = median;
std::cout << *iter << std::endl;
return *iter;
}
变量 end
没有正确指向向量的末尾。因此,您只对前 2 个元素执行 nth_element()
。由于变量median
值为1,所以返回x值较大的点。
您可以使用 points.end()
而不是 points.begin() + end
。
如果你仔细阅读了CPP参考资料here中对函数的描述,你会看到:
nth_element is a partial sorting algorithm that rearranges elements in [first, last) such that: The element pointed at by nth is changed to whatever element would occur in that position if [first, last) were sorted.
对您的问题很重要的是 [first, last)
,它表示半开范围。
根据定义,half-open 范围是包含第一个元素的范围,但 NOT 最后一个元素。最后一个不包括在内。如果要包含它,则需要更进一步。在你的情况下:last+1.
所以,你只是用错误的参数调用函数。没问题。
正确的代码可能是这样的:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
struct Point {
int x{};
int y{};
int getX() const { return x; }
int getY() const { return y; }
friend std::ostream& operator << (std::ostream& os, const Point& p) {
return os << p.x << ' ' << p.y;
}
};
template <typename Iterator>
Point get(Iterator start, Iterator median, Iterator end)
{
std::nth_element(
start,
median,
end,
[](const Point& point1, const Point& point2) {
return point1.getX() < point2.getX();
}
);
std::vector<Point>::iterator iter = median;
return *iter;
}
int main() {
std::vector<Point> points = { Point {70, 70}, Point {50, 30}, Point {35, 45} };
int start = 0, end = 2;
int median = (start + end) / 2;
Point split = get(points.begin() + start, points.begin() + median, points.begin()+end+1);
std::cout << split << '\n';
}