【发布时间】:2011-02-06 22:06:03
【问题描述】:
确定对std::sort(begin, end) 的调用是否实际修改了范围的最优雅方法是什么?
这是我的两个想法:
(a) 检查是否已经排序 O(n):
if (already_sorted(begin, end)) { return false; }
std::sort(begin, end);
return true;
(b) 跟踪比较器的变化(这样安全吗?):
bool modified = false;
std::sort(begin, end, [&modified](T a, T b){ modified |= a<b; return a<b; });
return modified;
有没有更好的办法?
【问题讨论】:
-
在我的脑海中,我不认为 (b) 是安全的:算法可以测试
comp(b, a)而不是comp(a, b),如果结果是false则交换。跨度> -
我认为一个更好的问题是为什么你需要知道范围是否已经排序——也许你应该选择一种排序算法,以“安全”的方式处理已经排序的范围,所以你不要'不必关心范围是否已排序?
-
@Jeff:我的应用程序有一个可能产生排序范围的过程。如果不是,则需要重复几个步骤。
-
(a) 的效率将取决于在您的上下文中数据通常是否已经排序。如果它通常是排序的,那么你已经完成了 O(N) 操作并为自己节省了 O(N log N)。但是,如果大部分数据还没有排序,那么你会不断地将 O(N) 添加到 O(N log N) 中,无论如何你总是这样做。在这种情况下,不检查直接排序可能是最有效的。特别是因为如果数据已经排序,我认为 std::sort 是 O(N) ......
-
(b) 对于典型的基于枢轴的排序方法肯定是错误的。在预先排序的范围内,他们会选择中间元素作为枢轴,并且 50% 的元素会小于枢轴。因此,对于包含 3 个或更多元素的预排序容器,至少与枢轴进行比较将设置为
modified。