为什么c++算法包含最多2*(count1+count2)-1的比较
why c++ algorithm includes have at most 2*(count1+count2)-1 comparisons
在阅读cplusplus.com的一篇文章时,我注意到它说了以下内容:
两个范围内距离的两倍以内为线性:执行最多
2*(count1+count2)-1
比较(其中countX是firstX和lastX之间的距离)。
然而,cppreference.com指出:
最多2·(N1+N2-1)比较,其中N1=std::distance(first1,last1)和N2=std:;distance(first2,last2)。
根据定义,N1==Count1和N2==Count2,哪个站点是正确的,谁能解释这个最大数量或比较是如何计算的,即:
- 定义这种最大复杂性的最坏情况是什么
- 有人能解释一下该场景中的步骤,并说明上面哪一个(cplusplus或cpprreference)具有正确的比较次数吗
警告:在所有阅读过该帖子的人(包括我)意识到他们不知道自己在说什么之前,这个答案的声誉就已经增加了。如果在未来的某个时候,有一个公认的答案与该算法的所有文档都不一致,请更加注意!
简而言之:
2*(任意)位很容易解释,我已经在下面做了解释。这一点让我非常困惑,据我所知,这应该是
2*(count1)
并且与第二范围的长度完全无关。要么我遗漏了什么(很可能),要么文档有误(这不是很好吗…)
如果你想要我的推理,请参阅下文。如果我错了,有人回答对了,请告诉我,这样我就可以删除这篇帖子了!
为什么是2*(计数1等)
如果你问为什么是2次(count1+count2)-1,关键在这一行:
使用运算符<对于第一个版本,comp用于第二个版本。如果(!(a<b)&!(b<a))或者如果(!comp(a&comp(b,a))。
每次它比较两个元素时,都会进行两次比较:我不等于它吗?它不等于我吗?
最大这些";比较对";它要做的是非常难以确定。事实上,我想不通。据我所知,这应该与第二范围的长度无关。。。
为什么不是(count1+count2-1)或(count1+count 2)-1
我已经研究了好几天了,并根据cpprreference中的代码示例进行了一些测试,老实说,我不知道这怎么可能是真的。
这些算法意味着,OP挖掘的一个来源说range2必须是range1的子集,并且两者都是排序的,所以没有必要对一个元素进行两次检查。这意味着算法最多必须检查range1的所有元素,如果range2的元素大于range1中的任何元素,则需要额外检查一次。不仅如此,范围2中哪里有2或20个元素并不重要,它仍然可以进行完全相同的比较。
比较有两种潜在的定义,显然会给出不同的答案:
comparison==算法中的所有比较操作
在这种情况下,会发生以下比较:
- 我达到最后一个范围了吗
- 我达到最后一个范围了吗
- 是range2-elem<range1 elem
- 是range2 elem>range1 elem
在简单的情况下,N1==N2==1,这可以生成至少6个比较(例如,1、2、3、4、1、2:其中range1={1}和range2={10}),这远远超过了任一算法所允许的范围。所以不可能是这样。
比较==检查elem1和elem2是否相等
在这种情况下,对范围1的每个元素都有两次比较,直到它找到范围2的所有元素,或者它到达范围1的末端,在那里它停止(在发现它已经到达范围1末端时)。
因此,据我所知,复杂性与N2的长度无关,复杂性应该是
2*(N1)
注意,对于";"比较";,2*(N1+N2-1)似乎只在N2==1时成立,而2*(N1+N2)-1从不成立,因为在非最大复杂度的情况下比较的数量只是奇数(范围2的数字不在范围1内且不大于最大值(范围1))。
任何其他的比较定义都是有选择性的。我唯一能想到的另一件事是,编译器优化了某些步骤,比如当元素没有增加时,不检查它是否再次到达范围2的末尾(这也会使算法根据需要依赖于N2),但我看不出还有什么可以优化的,以便将数字降到与上述两种复杂性完全匹配的程度。
还有谁能得到更好的答案?我现在和OP一样对此感到好奇。
首先,它必须进行两次比较来检查等价性,定义为:
if (!(a<b) && !(b<a))
或
if (!comp(a,b) && !comp(b,a))
那么它必须将每个可能的范围的整体相互对照减去1。
关键在这一行
两个元素a和b被认为是等价的if!(a<b)&!(b<a)或if!comp(a,b)&!comp(b,a)
让我们以小于谓词<和排序的集合
[2,3]
[1,2,3,4]
比较元素2和1:2<1返回false,因此它们可以是等效元素,或者2可以大于1。如果它们是等价的,则1<2也会返回false,但不会。因此,对于第二集合丢弃1,并且接下来考虑第二集合的值2。
最大比较数:2*(M+N)-1。该算法在O(N+M)中运行。
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么比较运算符如此快速
- 我可以使用 g++ 进行三种比较 (<=>) 吗?
- 比较字符数组
- 将模板化的类型与C++中的某些类/类型进行比较
- C++自定义比较函数
- 如何比较自定义类的std::变体
- 多个If语句与使用逻辑运算符计算条件的单个语句的比较
- std::设置自定义比较器
- 布尔比较运算符是如何在C++中工作的
- C++将目录中的所有文件与::filesystem进行比较
- shell排序中的交换和比较
- 如何在C++中比较两个char数组
- catch框架有没有办法比较流或文件
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 智能指针作为无序映射键,并通过引用进行比较
- 比较if语句中的数组值和int值
- 对于循环变体比较
- 使用自定义比较函数使用std::sort()对矢量字符串进行排序时出现问题
- 为什么c++算法包含最多2*(count1+count2)-1的比较