对于插入排序,如果存在一组 n 个递减元素,则情况更糟。 比较所有元素从左到右的总时间为:
1 + 2 + ... +(n-2)+(n-1)
在计算时间复杂度时还考虑的是交换这些元素,这也是:
1 + 2 + ... +(n-2)+(n-1)
最终,我们得出O(n ^ 2)。
采用另一种算法,例如二进制搜索; 找到中点的动作,然后将其与该中点进行比较,然后在列表的每个分区中将中点重新分配给high
或low
一半的时间根本不算时间复杂度。仅将中点与目标值进行比较的操作。 那么为什么经典的排序算法(三个赋值语句)中的交换会影响时间复杂性,而二进制搜索中的中点赋值却没有呢?
更新
在二进制排序中,在树结构中查找比在数据结构为数组/列表的插入排序中便宜。插入排序的病理情况是,每个元素都必须交换过去列表中已经存在的所有其他元素。
但是“交换”是否真的只是三个变量分配?
if (a[i] > a[j])
x = a[i];
a[i] = a[j];
a[j] = x;
与一般的二进制搜索算法中看到的以下情况相比,这三种分配如何占主导地位?
while(low < high)
mid = (low + high) / 2; // assignment 1
if (data[mid] == target)
return true;
if (data[mid] < testValue)
low = mid + 1; // assignment 2_a
else
high = mid; // assignment 2_b
答案 0 :(得分:1)
他们做到了!
在插入排序中,您执行O(n²)比较和O(n²)分配,但总数仍为O(n²)。
在二进制搜索中,您执行O(Log n)比较和O(Log n)分配,但总数仍为O(Log n)。
但是,通常的做法是,当您知道某项操作是按另一种操作进行的(例如,在二进制搜索中,每个比较执行一次赋值)时,只计算一种类型的操作。
顺便说一句,请考虑还有其他未考虑的操作,例如数组取消引用或循环语句。只要使用的操作数保持成比例(或较低的数量级),就可以使用big-Oh表示法。
其他示例:
一个人可以通过二分查找和交换来实现插入排序。
在这样的版本中,您将执行大约
Log 1 + Log 2 + Log 3 + Log n-1比较,即O(n Log n),
,仍然是O(n²)交换。在全球范围内,算法行为为O(n²)。
在复杂性分析中,您可以省去对比较进行计数,因为它们以较低的数量级起作用,并且只关心分配。 提供了这种不平衡状态!
答案 1 :(得分:-1)
没有一种一致的时间复杂度度量方法。
对于排序算法,基本操作被视为比较(仅此而已)。哈希表操作也是如此-它计算完成的比较次数。最好将“ mergesort的时间复杂度为O(n log n)”表示“ mergesort进行O(n log n)比较”。最好将“哈希表查找平均为O(1)”理解为“哈希表查找平均执行O(1)比较”。
这是使事情保持简单的必要条件-例如,如果对字符串数组进行排序,则字符串比较在基本操作中不是O(1)-开销取决于字符串的长度。如果您尝试忽略此问题并说“假设我们的计算机可以在O(1)中执行比较”,则会发现排序算法可以执行少于n log n个基本操作。我有一个(rather technical) blog post about this,其中包括对(甚至更具技术性的)文献的一些引用。
在考虑其他算法时,您可以测量基本运算(例如,赋值,算术运算等)。即使这样,有时您仍可能会认为算术运算的成本是恒定的,或者取决于操作数的大小。
几乎所有偶然性复杂度理论的使用都忽略了“时间”的含义上的差异,人们将很高兴地使用不同的时间概念来组合和比较不同的分析。这在实践中效果很好,并给出了有用的结果,但从理论上讲并不合理。