From ba403fcde04e4fba712de59063bcaeac220fda38 Mon Sep 17 00:00:00 2001 From: Shine wOng <1551885@tongji.edu.cn> Date: Thu, 16 May 2019 18:31:13 +0800 Subject: [PATCH] some small modifications --- thu_dsa/chp2/chp2.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/thu_dsa/chp2/chp2.md b/thu_dsa/chp2/chp2.md index fc6f0f3..c4bc97f 100644 --- a/thu_dsa/chp2/chp2.md +++ b/thu_dsa/chp2/chp2.md @@ -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::search(T e, int lo, int hi){ 但是邓公说,对于这种经常要用到的算法,还需要考察它复杂度的系数。所以实际上它的时间复杂度是$O(1.50logn)$,这个证明暂时还不会。我们对这个算法进行一个细致的分析: -可以看到,这个算法虽然是_二分_查找,可是实际上左右两边的操作时间并不是平衡的,进入左边需要更高的时间代价。这是因为进入右边只需要一次比较,而进入左边需要两次比较,所以左边的时间代价更高。左右两边不平衡会导致这个算法的运行速度变慢,也意味着还有可以优化的办法。 +可以看到,这个算法虽然是二分查找,可是实际上左右两边的操作时间并不是平衡的,进入右边需要更高的时间代价。这是因为进入左边只需要一次比较,而进入右边需要两次比较,所以右边的时间代价更高。左右两边不平衡会导致这个算法的运行速度变慢,也意味着还有可以优化的办法。 > 斐波拉契查找 @@ -287,7 +287,7 @@ int Vector::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::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)$的时间代价就可以完成。