l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表 num=200 for item in l: if num == item: print('find it') break
此寻找数字的方法,效率低;并且如果查找402,那么最后break就没有什么意思了。
下面用二分法:(一)
l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表 def get(num,l): mid=len(l)//2 if num > l[mid]: #in the right l=l[mid+1:] elif num < l[mid]: #in the left l=l[:mid] else: print('find it') return get(num,l) get(200,l)
由
def get(num,l): mid=len(l)//2 if num > l[mid]: #in the right l=l[mid+1:] get(num, l) elif num < l[mid]: #in the left l=l[:mid] get(num, l) else: print('find it') return get(200,l)
得来!
下面开始优化,得到寻找次数,和当前的中间值(二)
l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表 def get(num,l): mid=len(l)//2 print(l,l[mid]) if num > l[mid]: #in the right l=l[mid+1:] elif num < l[mid]: #in the left l=l[:mid] else: print('find it') return get(num,l) get(200,l)
问题来了,如果想要取的值不存在呢? get(3,l)
IndexError: list index out of range [1, 2, 10, 30, 33, 99, 101, 200, 301, 402] [1, 2, 10, 30, 33] [1, 2] []
数值不存在的情况下,列表切空了也找不到这个值。
解决方法如下:
l=[1,2,10,30,33,99,101,200,301,402] #从小到大排列的数字列表 def get(num,l): print(l) if len(l) > 0: #列表不为空,则证明还有值是可以执行二分法逻辑的 mid=len(l)//2 if num > l[mid]: #in the right l=l[mid+1:] elif num < l[mid]: #in the left l=l[:mid] else: print('find it') return get(num,l) else: #列表为空,则证明根本不存在要查找的值 print('not exists') return get(403,l)
找到值的索引,代码如下:
1 l=[1,2,10,30,33,99,101,200,301,402] 2 3 def search(num,l,start=0,stop=len(l)-1): 4 if start <= stop: 5 mid=start+(stop-start)//2 6 print('start:[%s] stop:[%s] mid:[%s] mid_val:[%s]' %(start,stop,mid,l[mid])) 7 if num > l[mid]: 8 start=mid+1 9 elif num < l[mid]: 10 stop=mid-1 11 else: 12 print('find it',mid) 13 return 14 search(num,l,start,stop) 15 else: #如果start > stop则意味着列表实际上已经全部切完,即切为空 16 print('not exists') 17 return 18 19 search(301,l)