C++等语言自带的sort函数使用的排序算法基本都是快速排序,快速排序是一种不稳定的排序算法,也就是说两个相等的元素排序前后的相对位置是有可能变化的。在使用sort对一个有偏序关系的序列进行拓扑排序时,比较函数的设计要特别注意。例如我们对格点(x,y)进行排序,使得如果有x0 <= x1 而且 y0 <= y1时,(x0,y0)在(x1,y1)前面。
代码大致如下:
const int N = 10;
struct Node {
int x, y;
void init(int _x, int _y) {
x = _x;
y = _y;
}
}node[N * N];
bool cmp(const Node &a, const Node &b) {
}
int main() {
int n = 0;
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
node[n++].init(i, j);
}
}
for (int i = 0; i < N * N; ++i) {
swap(node[i], node[rand() % (N * N)]);
}
sort(node, node + n, cmp);
for (int i = 0; i < N; ++i) {
printf("%d %d\n", node[i].x, node[i].y);
}
return 0;
}
非常直观地,也许我们会把比较函数设计成:
bool cmp(const Node &a, const Node &b) {
return a.x <= b.x && a.y <= b.y;
}
但是这样的结果很可能不是我们所要的,我们确定了这么个比较关系之后,所有不满足的这个关系的两个元素进来比较,都会被认为第一个应该在第二个后面。
正确的,应该设计成这样:
bool cmp(const Node &a, const Node &b) {
return a.x < b.x || a.x == b.x && a.y < b.y;
}
这其实是将一个偏序关系全序化,容易理解这个比较函数包含了前面那个比较函数的内容。