some small modifications
This commit is contained in:
@@ -90,7 +90,7 @@ T(n) = O(n^2)
|
||||
$$
|
||||
分摊到每次操作的时间成本为$O(n)$
|
||||
|
||||
同样,接下来再考虑加倍策略。同样是最坏情况下,连续进行了n次插入操作。假定初始的容量为,每次扩容所需要的时间成本为:
|
||||
同样,接下来再考虑加倍策略。同样是最坏情况下,连续进行了n次插入操作。假定初始的容量为1,每次扩容所需要的时间成本为:
|
||||
$$
|
||||
1, 2, 4, 8, ..., n
|
||||
$$
|
||||
@@ -197,7 +197,7 @@ int Vector<T>::search(T e, int lo, int hi){
|
||||
|
||||
但是邓公说,对于这种经常要用到的算法,还需要考察它复杂度的系数。所以实际上它的时间复杂度是$O(1.50logn)$,这个证明暂时还不会。我们对这个算法进行一个细致的分析:
|
||||
|
||||
可以看到,这个算法虽然是_二分_查找,可是实际上左右两边的操作时间并不是平衡的,进入左边需要更高的时间代价。这是因为进入右边只需要一次比较,而进入左边需要两次比较,所以左边的时间代价更高。左右两边不平衡会导致这个算法的运行速度变慢,也意味着还有可以优化的办法。
|
||||
可以看到,这个算法虽然是<em>二分</em>查找,可是实际上左右两边的操作时间并不是平衡的,进入右边需要更高的时间代价。这是因为进入左边只需要一次比较,而进入右边需要两次比较,所以右边的时间代价更高。左右两边不平衡会导致这个算法的运行速度变慢,也意味着还有可以优化的办法。
|
||||
|
||||
> 斐波拉契查找
|
||||
|
||||
@@ -287,7 +287,7 @@ int Vector<T>::interpolation_search(T const &elem, int lo, int hi){
|
||||
}
|
||||
```
|
||||
|
||||
插值查找在平均情况下,每经过一次比较,规模从$n$缩减到$\sqrt(n)$,其平均时间复杂度为$O(loglog n)$(需要证明,但是目前不会)。这个结果虽然看起来很理想,但是在目前人类的数据量看来,和$O(logn)$相比并不占多大优势(考虑$2^64$的数据量)。
|
||||
插值查找在平均情况下,每经过一次比较,规模从$n$缩减到$\sqrt{n}$,其平均时间复杂度为$O(loglog n)$(需要证明,但是目前不会)。这个结果虽然看起来很理想,但是在目前人类的数据量看来,和$O(logn)$相比并不占多大优势(考虑$2^{64}$的数据量)。
|
||||
|
||||
此外,插值查找在大数据量的输入下,表现会比较好。但是,一旦数据量缩小到一定范围,就容易受到局部扰动的影响,从而耽误大量的时间,例如整体的数据分布是线性分布,却又一个小局部不满足线性分布,是二次分布的。所以,理想的查找方法是
|
||||
|
||||
@@ -323,7 +323,7 @@ bool Vector<T>::bubble(int lo, int hi){
|
||||
|
||||
> 对上面版本的冒泡排序进行优化
|
||||
|
||||
考虑一种情况,即一个规模为n的Vector中,已经是局部有序了,只有前面k个元素是无序的。使用上面的算法的话,在最坏情况下,时间复杂度为$O(n * k)$。假定$ k = \sqrt(n)$,则时间复杂度为$O(n^{3/2})$。
|
||||
考虑一种情况,即一个规模为n的Vector中,已经是局部有序了,只有前面k个元素是无序的。使用上面的算法的话,在最坏情况下,时间复杂度为$O(n * k)$。假定$ k = \sqrt{n}$,则时间复杂度为$O(n^{3/2})$。
|
||||
|
||||
但是实际上,它根本不需要这么高的时间复杂度。因为要是可以检测到该序列的局部有序性,只给前面的k个元素排序的话,就只需要$O(k^2) = O(n)$的时间代价就可以完成。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user