Как получить указатель на элемент списка, который остается после сортировки в C ++ - PullRequest
0 голосов
/ 15 апреля 2019

Я держу несколько двумерных точек с координатами xy в списке.У меня есть метод, который сортирует массив по расстоянию между точками с курсором, и метод возвращает указатель на точку, ближайшую к курсору.

Однако я использую & points.first () иэто всегда указывает на первый элемент списка.Однако указатель меняется после того, как я прибегаю к списку.Как получить указатель, который указывает на конкретный элемент, а не на первый элемент списка.

Я пробовал: & points.first ()

QList<Point2> points;


Point2 *DrawingWidget::closestToCursor(){
    // Current mouse position
    Point2 pos(m_x, m_y);

    // There are no points
    if(points.isEmpty()){
        return NULL;
    }

    // Sorts according to distance to the cursor
    std::sort(std::begin(points), std::end(points), [&pos](Point2 a, Point2 b) {
            return pos.distanceFrom(a) < pos.distanceFrom(b);
    });

    // We dont allow points closer than 50px appart
    if(pos.distanceFrom(points.first()) > 50){
        return NULL;
    }

    // Even after the resort, this always points to the first element of the vector. How do I get this elements pointer instead? 
    // Currently it seems that the pointer is basically LIST+0x0, however if the element shifts to whatever position, how do I still have its pointer?
    return &points.first();
}

Каждый раз, когда я звонюэтот метод рядом с новой точкой, указатель просто перемещается к первому элементу списка, и это то, что он должен делать, я знаю это.Но как мне сделать это так, как мне нужно?

Ответы [ 2 ]

1 голос
/ 15 апреля 2019

Вам, вероятно, следует выполнить линейный поиск, чтобы найти этот элемент, поскольку сортировка обходится дороже.

Линейный поиск - O(N).

Сортировка - O(N*log2(N)).

Например:

auto& found = *std::min_element(std::begin(points), std::end(points),
                                [&pos](Point a, Point b) { return pos.distanceFrom(a) < pos.distanceFrom(b); });
return pos.distanceFrom(found) > 50 ? 0 : &found;
0 голосов
/ 15 апреля 2019

Поскольку ваш список отсортирован, вы можете найти исходную первую точку за log2(n) шагов, используя двоичный поиск:

#include <algorithm>

Point2 *DrawingWidget::closestToCursor() {
    if (points.isEmpty())
        return NULL;
    Point2 pos(m_x, m_y);
    auto cmpfun = [&pos](Point2 a, Point2 b) {
            return pos.distanceFrom(a) < pos.distanceFrom(b);
    });
    auto firstPoint = points.first();

    std::sort(std::begin(points), std::end(points), cmpfun);
    if (pos.distanceFrom(points.first()) > 50)
        return NULL;

    // return a pointer to the original first point
    return &*std::lower_bound(std::begin(points), std::end(points),
                              firstPoint, cmpfun);
}

Существуют и другие подходы, такие как decorate-sort-undecorate , чтобы отсортировать указатели и действительно сохранить исходную точку, но они, вероятно, в конечном итоге будут значительно дороже выполнять.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...