计算机原子操作(来源:数据结构与算法python语言实现)
一个原子操作相当于一个低级别的指令,其执行时间是常数,在理想情况下,这可能是被硬件执行的基本操作类型,
常见的原子操作:
- 给对象指定一个标示符
- 确定与这个标示符相关的对象
- 执行算术运算(例如,加法)
- 比较两个数的大小
- 通过索引访问python列表的一个元素
- 调用函数
- 函数返回
分析算法时,存在几种可能的考虑:
- 算法完成工作最少需要多少基本操作,即最优时间复杂度
- 算法完成工作最多需要多少基本操作,即最坏时间复杂度
- 算法完成工作平均需要多少基本操作,即平均时间复杂度
对于最优时间复杂度,其价值不大,因为它没有提供什么有用信息,其反映的只是最乐观最理想的情况,没有参考价值。
对于平均时间复杂度,是对算法的一个全面评价,因此它完整全面的反映了这个算法的性质。但另一方面,这种衡量并没有保证,不是每个计算都能在这个基本操作内完成。
对于最坏时间复杂度,提供了一种保证,表明算法在此种程度的基本操作中一定能完成工作。故一般我们按照最坏的情况把算法的运行时间表示为输入大小为n的函数。
常用的函数
1 常数函数 f(n) = c
他描述了计算机上需要做的基本操作的步数,例如上面的所列的常见的原子操作。例如:
def square(x):
return x*x
2 对数函数 x = logn(以2为底)
常见的在许多算法中的,反复把一个输入分成两半, 例如二分查找算法
关键点: log16=4,也可以这样计算:(((16/2)/2)/2)/2=1,则log16=4,即对正整数n,用n除以2,只有当结果小于等于1时才停止除法操作。logn的值即为n除以2的次数。{(((16/2)/2)/2)/2=1,可以看做是反复把输入分成两半}
对特殊情况,log12=4,是因为(((12/2)/2)/2)/2=0.75<=1,一般会对特殊情况向上取整,近似计算,
def bi_search_iter(alist,item):
left,right = 0,len(alist)- 1
while left <= right:
mid = (left+right)//2
if alist[mid] < item:
left = mid + 1
elif alist[mid] > item:
right = mid - 1
else:
return mid
return -1
num_list = [1,2,3,4,5,6,7,8]
print(bi_search_iter(num_list,8))
7
3 线性函数 f(n)=n
这个函数出现在我们必须对所有n个元素的做基本的操作的算法分析的任何时间,例如,比较数字x与数组大小为N的每一个元素,需要做n次的比较。例如:
def findMax(lists):
if lists == None:
return None
maxNum = lists[0]
for i in lists:
if i > maxNum:
maxNum = i
return maxNum
lists = [3,4,6,2,8,28]#最大的数在最后,要找到最大数,至少要比较6次
print(findMax(lists))
28
4 nlogn函数 f(n)= nlogn
经常出现在对n个任意数进行排序中,
5二次函数 f(n) = n^2
许多算法中都有嵌套循环,内层循环和外层循环,算法执行的时间为n*n=n^2
number = [[12,23,45],[34,56,78],[12,34,56]]
for i in range(len(number)):
for j in range(len(number[i])):
print(number[i][j])
12
23
45
34
56
78
12
34
56
6 三次函数 f(n) = n^3
这个函数在算法分析中比较少见。
评估算法运行时间
假设T(a) 最慢的基本操作所需的时间,T(n)为算法运行的时间,T(b)为最快的基本操作时间,三者应满足上式关系,
故在评价运行时间时,通常使用近似法表示,
常见的近似法有:
- Big-O记法,
- Big-Theta记法
- Big- Omega记法
Big-O记法(下图来自万门大学)
Big-Theta记法
Big- Omega记法