接上一篇文章继续分析
在之前的文章中的示例1和示例2中,我们通过观察可以发现,当在顺序存储结构的线性表中某个位置上插入或删除一个数据元素时,其时间主要耗费在移动元素上(换句话说,移动元素的操作为预估算法时间复杂度的基本操作),而移动元素的格式取决于插入或删除元素的位置。
假设
p
i
是在第i个元素之前插入一个元素的概率,则在长度为n的线性表中插入一个元素时所需移动元素次数的期望值(平均次数)为
(1)
E
i
s
=
∑
i
=
1
n
+
1
p
i
(
n
−
i
+
1
)
假设q_i是删除第i个元素的概率,则在长度为n的线性表中删除一个元素时所需移动元素次数的期望值(平均次数)为
(2)
E
d
l
=
∑
i
=
1
n
q
i
(
n
−
i
)
为了不失一般性,我们可以假定在线性表上的任意位置上插入或删除元素都是等概率的,即
(3)
p
i
=
1
n
+
1
,
q
i
=
1
n
通过(3)我们可以将上面的(1)和(2)进行相应的简化,其简化结果为:
(4)
E
i
s
=
1
n
+
1
∑
i
=
1
n
+
1
(
n
−
i
+
1
)
=
n
2
(5)
E
d
l
=
1
n
∑
i
=
1
n
(
n
−
i
)
=
n
−
1
2
时间复杂度的计算规则:
1.去掉运行时间中的所有加法常数
2.只保留最高阶项
3.如果最高阶项存在且不是1,去掉与这个最高阶相乘的常数得到时间复杂度
由(4)和(5)可知,在顺序存储结构的线性表中插入或删除一个数据元素,平均约移动一般元素。若表长为n,则算法listInsert_
S
q
和listDelete_
S
q
的时间复杂度都为O(n)。
在示例1和示例2中的插入操作中,“求表长”和“取第i个数据元素”的时间复杂度均为O(1),又由于插入均在表尾进行,则不需要移动元素,因此它们的执行时间主要取决于查找函数locateElem的执行时间。
在示例1中,在顺序表L中查访是否存在和e相同的数据元素的最简单的方法是,令e和L中的数据元素逐个比较,若L中存在于e相同的元素
a
1
则比较次数为
i
(
1
≤
i
≤
L
.
l
e
n
g
t
h
)
,否则为L.length,即算法locateElem_
S
q
的时间复杂度为
O
(
L
.
l
e
n
g
t
h
)
。由此对于顺序表LA和LB而言,union的时间复杂度为
O
(
L
A
.
l
e
n
g
t
h
×
L
B
.
l
e
n
g
t
h
)
。
而在示例2中,基本操作主要是给“元素赋值”算法的时间复杂度为
O
(
L
A
.
l
e
n
g
t
h
+
L
B
.
l
e
n
g
t
h
)
。
总结:
通过上述两个示例我们不难看出,示例2中的程序其运算的时间复杂度更低,因而程序运行也就会更迅速。究其原因有二:
1) 由于la与lb中的元素依值递增(同一集合中元素不等),则在lb中的元素不需要在la中进行从头至尾的全程搜索;
2) 由于用新表lc表示“并集”,则插入操作实际上是借助于“复制”操作来完成的。
结论:
若以线性表表示集合并进行集合的各种运算,应该先对表中的元素进行排序。
其它:
下面再列出其它各种常用排序的时间复杂度表