先简单说一下概念:
算法:就是解决问题的方法、步骤;
数据结构:数据之间的相互关系(逻辑结构)+数据的逻辑结构在计算机中的存储(物理结构)
简单说一下两种数据结构:
数组:内存连续的一种数据存储。就是申请一块内存,挨个存放数据,地址连续,通过索引(下标)获取存储的数据;
缺点是:1.内存需要连续,容易溢出或者浪费内存;2.删除、添加都需要繁琐的移动后面的元素,不过高级语言都有封装好的添加删除函数;
优点是:读取元素很快,通过索引一步就可以,时间复杂度O(1);(大O表示法文末介绍)
链表:连续数据的内存不一定连续,每一个数据都存储下个数据的地址(详细的暂不讨论)
缺点是:查找是需要遍历整个链表;
优点是:删除和插入简单,一步即可
下面说第一个简单的算法:
抛出问题:查找26在不在数组[1,2,4,5,21,26,78,100]中
思考:最简单的,我们首先可以想到遍历这个数组,拿数组的每一个元素和26比较,如果相等就说明26在这个数组,否则则不在;这样走一遍的话需要的时间是O(n),就是从数组的第一个元素比较到最后一个元素,共比较n次;代码如下:
arr = [1,2,4,5,21,26,78,100]
def simple_search(arr,num):
# i markup search progress
i = 0
for x in arr:
if x == num:
print num ,'in this list'
else:
i = i + 1
if i == len(arr):
print num ,'not in this list'
simple_search(arr,26)
这只是几个数,如果我们数据太大,这样做的话就会费时很久,有没有快速一点的查找方法呢?以前聚会的时候可能玩过一个游戏:就是一个人想一个100以内的数,写在手机上,然后大家开始猜,猜一个数,写的人会告诉你大了还是小了,依次下去,直到最后只剩一个数,谁最后猜中了,就会被惩罚。这个时候如果你想快点结束游戏的话,你会怎么做呢,当然是对半猜,先猜50,然后25或者75,依次下去,很快就会猜出答案。这其实就是我们今天要说的简单的查找算法:折半查找(二分查找):
原理如上面的游戏,先拿到数组中间的数arr[len/2-1],然后和你要找的数对比,然后按照上面所说不断折半,直到low>=high结束查找。代码如下:
arr = [1,2,4,5,21,26,78,100]
def binary_search(arr,num):
low = 0
high = len(arr) - 1
while low < high:
mid = (low+high) / 2 #python automatic downward alignment
tem = arr[mid]
if num == tem:
print num ,'in this list'
elif num < tem:
high = mid - 1;
else:
low = mid + 1
print num ,'not in this list'
binary_search(arr,26)
那么折半查找的时间复杂度是多少呢,我们可以简单的理解为对折,一个长为n的数组,对折下去,直到找到,最坏的情况复杂度为log(n),就是要找的数是第一个或最后一个,最好的是O(1),就是第一次对折就找到了。一般没其他标示的话,大O标示的是最坏情况的时间复杂度。
任何算法都是有缺陷的,或者说限制,折半查找的缺陷很好看:
1.作用于数组
2.数组有序
二分查找还有很多有趣的用处,感兴趣的可以下去找着玩玩,本节只介绍基本的理解和实现。
大O表示法:
是一种表示算法执行速度的方法,形式是:O(n),n是操作数,即执行这个算法,一共需要多少步操作。上面说的简单查找(第一中方法)最坏情况是n步操作,所以是O(n),折半查找最坏需要logn步,是O(logn)