C++ 保持坐标排序

C++ 保持坐标排序,c++,algorithm,sorting,C++,Algorithm,Sorting,我有一些坐标(x,y),我需要对这些坐标进行排序并保持排序。在我对它们进行排序之后,每个坐标从(x,y)更改为(x+1,y)或(x-1,y)或(x,y-1)或(x,y+1),因此坐标不再排序 有没有更好的方法来解决这个问题?此外,排序坐标,坐标更改,再次排序坐标,坐标更改,根据每个坐标以+-1更改的条件再次排序坐标?a将为您处理所有这些。特别是,内容本质上是按集合成员的操作符排序的A将为您处理所有这些。特别是,内容本质上由集合成员的操作符进行排序更新坐标时,可以通过在更新后将坐标移动到正确的位置

我有一些坐标(x,y),我需要对这些坐标进行排序并保持排序。在我对它们进行排序之后,每个坐标从(x,y)更改为(x+1,y)或(x-1,y)或(x,y-1)或(x,y+1),因此坐标不再排序


有没有更好的方法来解决这个问题?此外,排序坐标,坐标更改,再次排序坐标,坐标更改,根据每个坐标以+-1更改的条件再次排序坐标?

a将为您处理所有这些。特别是,内容本质上是按集合成员的
操作符排序的A将为您处理所有这些。特别是,内容本质上由集合成员的
操作符进行排序更新坐标时,可以通过在更新后将坐标移动到正确的位置来保持排序顺序

如果您正在执行
(x+1,y)
(x,y+1)
,则坐标将位于向量中其当前位置的前面。如果正在执行
(x-1,y)
(x,y-1)
,则坐标将位于向量中当前位置的后面

(如果坐标相对于矢量中的其他元素仍然正确,则也可能不需要更改位置)

使用此选项,可以在前面(或后面)搜索更新的坐标需要移动的位置。搜索时,可以将元素向后(或向前)复制,以缩小当前元素留下的间隙

|   a   |   b   |   c   |   d   |
| {1,1} | {1,2} | {2,0} | {2,2} |

在上面的例子中,考虑我们更新<代码> C <代码>到<代码> {1,0} < /代码>。我们向后移动,检查

c
,这是真的,所以我们向前移动
b

|   a   |       |   b   |   d   |
| {1,1} |       | {1,2} | {2,2} |
我们再次向后移动,检查
c
,这也是正确的,因此我们向前移动
a

|       |   a   |   b   |   d   |
|       | {1,1} | {1,2} | {2,2} |
在这一点上,我们已经到达了向量的开头,所以我们知道
c
必须在这个位置

|   c   |   a   |   b   |   d   |
| {1,0} | {1,1} | {1,2} | {2,2} |
另一种终端情况是
c
不再小于正在检查的元素

这在前进方向上也同样有效

一些代码可以演示此想法:

#include <algorithm>
#include <ctime>
#include <iostream>
#include <random>
#include <vector>

struct Point {
    int x;
    int y;

    void Adjust(int i) {
        switch (i) {
            case 0: x++; return;
            case 1: y++; return;
            case 2: x--; return;
            case 3: y--; return;
        }
    }

    bool operator<(const Point & rhs) {
        if (x == rhs.x)
            return y < rhs.y;

        return x < rhs.x;
    }

    bool operator>(const Point & rhs) {
        if (x == rhs.x)
            return y > rhs.y;

        return x > rhs.x;
    }
};

int main() {
    std::vector<Point> points;

    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j)
            points.push_back({i,j});
    }

    std::sort(std::begin(points), std::end(points));

    std::default_random_engine rng{std::time(nullptr)};
    std::uniform_int_distribution<int> distrib{0, 3};

    for (int i = 0; i < 10000; ++i) {
        for (auto iter = std::begin(points); iter != std::end(points); ++iter) {
            auto p = *iter;
            int adjustment = distrib(rng);

            p.Adjust(adjustment);

            auto current = iter;

            if (adjustment < 2) {
                auto next = std::next(current);

                while (next != std::end(points) && p > *next) {
                    *current = *next;
                    current = next;
                    next = std::next(current);
                }

                *current = p;
            }
            else if (current != std::begin(points)) {
                auto prev = std::prev(current);

                while (p < *prev) {
                    *current = *prev;
                    current = prev;

                    if (current != std::begin(points))
                        prev = std::prev(current);
                    else
                        break;
                }

                *current = p;
            }
        }
    }

    for (auto && p : points)
        std::cout << "{" << p.x << "," << p.y << "}\n";

    std::cout << "is_sorted = "
        << std::is_sorted(std::begin(points), std::end(points))
        << std::endl;

    return 0;
}
#包括


免责声明:我尚未衡量此解决方案的性能。由于每个元素更新都会发生混乱,因此它可能比在所有更新之后对向量进行排序要慢。

在更新坐标时,可以通过在更新后将坐标移动到正确的位置来保持排序顺序

如果您正在执行
(x+1,y)
(x,y+1)
,则坐标将位于向量中其当前位置的前面。如果正在执行
(x-1,y)
(x,y-1)
,则坐标将位于向量中当前位置的后面

(如果坐标相对于矢量中的其他元素仍然正确,则也可能不需要更改位置)

使用此选项,可以在前面(或后面)搜索更新的坐标需要移动的位置。搜索时,可以将元素向后(或向前)复制,以缩小当前元素留下的间隙

|   a   |   b   |   c   |   d   |
| {1,1} | {1,2} | {2,0} | {2,2} |

在上面的例子中,考虑我们更新<代码> C <代码>到<代码> {1,0} < /代码>。我们向后移动,检查

c
,这是真的,所以我们向前移动
b

|   a   |       |   b   |   d   |
| {1,1} |       | {1,2} | {2,2} |
我们再次向后移动,检查
c
,这也是正确的,因此我们向前移动
a

|       |   a   |   b   |   d   |
|       | {1,1} | {1,2} | {2,2} |
在这一点上,我们已经到达了向量的开头,所以我们知道
c
必须在这个位置

|   c   |   a   |   b   |   d   |
| {1,0} | {1,1} | {1,2} | {2,2} |
另一种终端情况是
c
不再小于正在检查的元素

这在前进方向上也同样有效

一些代码可以演示此想法:

#include <algorithm>
#include <ctime>
#include <iostream>
#include <random>
#include <vector>

struct Point {
    int x;
    int y;

    void Adjust(int i) {
        switch (i) {
            case 0: x++; return;
            case 1: y++; return;
            case 2: x--; return;
            case 3: y--; return;
        }
    }

    bool operator<(const Point & rhs) {
        if (x == rhs.x)
            return y < rhs.y;

        return x < rhs.x;
    }

    bool operator>(const Point & rhs) {
        if (x == rhs.x)
            return y > rhs.y;

        return x > rhs.x;
    }
};

int main() {
    std::vector<Point> points;

    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j)
            points.push_back({i,j});
    }

    std::sort(std::begin(points), std::end(points));

    std::default_random_engine rng{std::time(nullptr)};
    std::uniform_int_distribution<int> distrib{0, 3};

    for (int i = 0; i < 10000; ++i) {
        for (auto iter = std::begin(points); iter != std::end(points); ++iter) {
            auto p = *iter;
            int adjustment = distrib(rng);

            p.Adjust(adjustment);

            auto current = iter;

            if (adjustment < 2) {
                auto next = std::next(current);

                while (next != std::end(points) && p > *next) {
                    *current = *next;
                    current = next;
                    next = std::next(current);
                }

                *current = p;
            }
            else if (current != std::begin(points)) {
                auto prev = std::prev(current);

                while (p < *prev) {
                    *current = *prev;
                    current = prev;

                    if (current != std::begin(points))
                        prev = std::prev(current);
                    else
                        break;
                }

                *current = p;
            }
        }
    }

    for (auto && p : points)
        std::cout << "{" << p.x << "," << p.y << "}\n";

    std::cout << "is_sorted = "
        << std::is_sorted(std::begin(points), std::end(points))
        << std::endl;

    return 0;
}
#包括


免责声明:我尚未衡量此解决方案的性能。它可能比在所有更新之后对向量进行排序要慢,因为每个元素更新都会发生混乱。

您如何准确地对它们进行排序?也就是说:
(x0,y0)<(x1,y1)
的确切含义是什么?此外,语言标记和有关您正在使用的数据结构的信息也会有所帮助。广义地说:每次排序都是O(nlogn)。但是,例如,当您有一个类似堆的数据结构时,您可能会删除坐标,更改坐标,然后重新插入(到新的排序位置),或者使用大致基于某种二进制搜索的内容。比如(x0,y0)=a,(x1,y1)=b。如果(x0Can't edit on the second line,我想说“Any other case a>b”*。那么这是一个简单的例子。我假设你有一个
vector
包含
std::pair
或类似的内容。然后我认为a或可能是一个不错的选择,但我的C++知识有点生疏,不足以扔掉一些(非常“好”)实现示例…我理解,谢谢,我将研究您到底是如何对它们进行排序的?也就是说:
(x0,y0)<(x1,y1)
的确切含义是什么?此外,语言标记和有关您正在使用的数据结构的信息可能会有所帮助。概括地说,每次排序都是O(nlogn)每次。但是当你有一个堆状的数据结构时,你可能会删除坐标,改变它,然后重新插入(到新的排序位置),或者使用一些大致基于某种二进制搜索的东西。比如说(x0,y0)=a,(x1,y1)=b。如果(x0)不能在我想说的第二行进行编辑“任何其他情况下a>b”*。那么这是一个简单的问题。我假设你有一个
向量
包含
std::pair
或类似的东西。然后我认为a或可能是一个解决办法,但我的C++知识有点太生疏了,不能扔掉一些(非常“好”)实现示例…我理解,谢谢,我将研究它