我有以下简单程序。在test1
和test2
中,我尝试对2个字符串“ 2”和“ 1”进行排序,在下面的示例中,函数compare
将始终返回false。
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cassert>
static inline bool compare(const std::string& a, const std::string& b)
{
if (isdigit(b[0]))
return false;
assert(isdigit(a[0]));
return true;
}
static inline void test1()
{
std::cout << "test1:\n";
std::vector<std::string> arr = {
"2", "1"
};
std::stable_sort(arr.begin(), arr.end(), compare);
for (auto e: arr)
std::cout << e << std::endl;
}
static inline void test2()
{
std::cout << "test2:\n";
std::vector<std::string> arr = {
"1", "2"
};
std::stable_sort(arr.begin(), arr.end(), compare);
for (auto e: arr)
std::cout << e << std::endl;
}
static inline bool compare_int(const int& a, const int& b)
{
return a > b;
}
static inline void test3()
{
std::cout << "test3:\n";
std::vector<int> arr = {
9, 3, 13, 7
};
std::stable_sort(arr.begin(), arr.end(), compare_int);
for (auto e: arr)
std::cout << e << ' ';
std::cout << std::endl;
}
int main()
{
test1();
test2();
test3();
return 0;
}
但是,我得到以下输出
test1:
2
1
test2:
1
2
test3:
13 9 7 3
我很困惑,因为据我所知,test1和test2中的compare
函数将返回false,这表明这两个元素应该交换它们的位置。但是显然,它们没有改变,仍然保留在原始位置。
我误解了比较函数的返回值吗?但是在test3
中,它确实是按降序排序的。
我不太了解其内部结构,它是否以不同于整数的方式对待字符?
答案 0 :(得分:2)
我要回答自己的问题,但是非常感谢PaulMckenzie在讨论中的帮助以及Victor Istomin的回答。
事实证明,这种排序方式并不符合我的预期。它期望严格弱阶,这意味着a > b
和b > a
不能同时为真,否则行为为未定义。另外,它判断2个元素是否相等的方法是使用!(a < b) && !(b > a)
,因为它仅使用<
运算符而不是==
运算符。
我的代码中的错误是,在这种情况下,我总是返回false,这样表达式!(a < b) && !(b > a)
将为true,并且sort认为它们相等,因此不进行交换。
PaulMckenzie指出,正确的解决方案是使用stable_partiion
(如果不需要相对顺序,则使用partition
)。原理是仅在我们有比较元素的明确规则时才使用排序,如果我们只想将相同元素分组在一起,则partition
是好的。
似乎我对排序函数有一些错误的幻想,谢谢指出。
-----------------更新----------------
Caleth在评论中指出,严格弱顺序未强制执行,但如果违反,行为将是不确定的。更新了我对该部分的描述。谢谢。
答案 1 :(得分:0)
“比较”功能与您编写的功能完全相同:如果第二个字符串的第一个字符为digit,则返回false。
顺便说一句,在一般情况下,此比较功能将无法按预期运行(无论您期望如何,我都不知道)。在C ++中,排序比较器应实施严格的弱排序。换句话说,不应同时存在“ a