C++ 保持坐标排序
我有一些坐标(x,y),我需要对这些坐标进行排序并保持排序。在我对它们进行排序之后,每个坐标从(x,y)更改为(x+1,y)或(x-1,y)或(x,y-1)或(x,y+1),因此坐标不再排序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将为您处理所有这些。特别是,内容本质上由集合成员的操作符进行排序更新坐标时,可以通过在更新后将坐标移动到正确的位置
有没有更好的方法来解决这个问题?此外,排序坐标,坐标更改,再次排序坐标,坐标更改,根据每个坐标以+-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++知识有点太生疏了,不能扔掉一些(非常“好”)实现示例…我理解,谢谢,我将研究它