二分查找
来源:互联网 发布:java 线程之间通信 编辑:程序博客网 时间:2024/05/16 12:29
二分查找顾名思义,平分成两份查找(以网易云课堂 第六周作业为例,使用Python语言)
两点入门二分查找:
a. 猜测的值 = 中间值 =(low+high)/2 —— 二分的意义
b. 中间值<实际值,low = 中间值位置+1;中间值>实际值,high = 中间值-1
提供一个简易的代码模板(默认能够找到——如果不存在这个值也没必要查找了,提前使用in来判断是否存在):
def search(sequence, number, lower, upper): if lower == upper: assert number == sequence[upper] # 断言一定能找到,找不到则异常 return upper else: middle = (lower + upper)//2 if number > sequence[middle]: return search(sequence, number, middle+1, upper) else: # there has 2 situation--middle is not (middle-1) return search(sequence,number,lower,middle)
一些实例:
1.定义一个 prime() 函数求整数 n 以内(不包括n)的所有素数(1不是素数),并返回一个按照升序排列的素数列表。使用递归来实现一个二分查找算法函数bi_search(),该函数实现检索任意一个整数在 prime() 函数生成的素数列表中位置(索引)的功能,并返回该位置的索引值,若该数不存在则返回 -1。
思考:
要查找位置并且返回索引值,一般解决方法很简单:使用循环判断 / 列表的index方法,但是要是列表很长东西很多,那么这样的从头开始循环的话则效率会很低,那么使用二分查找。
解:
说到递归函数,不得不再一次强调:一定要有终止条件返回;非终止条件的递归过程,调用自身前面一定要有return,否则返回的是None。
这道题中的终止条件便是:返回该位置的索引值,若该数不存在则返回 -1
def prime(n): lst = [] for i in range(2, n): for j in range(2, i): if i % j == 0: break else: lst.append(i) return lstn = 10 # assume n = 10lst = prime(n)x = raw_input("Enter num: ")x = int(x) # raw_input() return a stringdef bi_search(x, low, high): guess = (low + high) / 2 print lst[guess], x if (x == lst[guess]): return guess elif low > high: return -1 elif lst[guess] > x: print 'lst[guess] > x' return bi_search(x, low, guess -1) # !!! take care elif lst[guess] < x: return bi_search(x, guess + 1, high) # !!! take care
再次通过同学ZHT的启发,简化下程序:首先利用Python 的 “in” 运算符判断数字是否在列表内(先决条件),再进行查找。
既然循环的先决条件是有x 存在于列表当中,所以必然就是能够找到的 x 的位置的,故终止条件只有一个:x 的位置
def bi_serach(lst,n): lenth = len(lst) while n in lst: if n == lst[lenth / 2]: return lenth / 2 elif n < lst[lenth / 2]: lst = lst[:lenth / 2] return bi_serach(lst,n) else: lst = lst[lenth / 2 + 1:] return bi_serach(lst,n) + lenth /2 + 1 # after slicing you must do return -1 # same indent with "While"上述程序有一个需要注意的地方:切片操作,往后切片之后一定要注意下标的变化要还原,之前提到过这样一个问题:“注意细节上的逻辑错误,在swap中,第二个参数不能够直接传mi,因为 mi 是在砍掉了 i 项之后的 nLst 中的位置 ≠ lst中的位置, 所以需要给mi 补上 i 才是 lst 中正确的位置。”
另外,使用循环实现二分查找:
同样需要找准终止条件,依然是:找到了 & 没找到的情况
逻辑是:没有找到就持续循环,找到了就return,故循环结束条件就是没有找到任何匹配position。
def bi_search(x, low, high): while high >= low: guess = (high + low) / 2 if x == lst[guess]: return guess elif lst[guess] > x: high = guess - 1 else: low = guess +1 return -1
当然,可以依照上述递归的方法也进行改装(循环的先决条件是,x 存在于列表当中),只需要将 while 条件(修改 while high >= low: )
while x in lst:改变即可。
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 二分查找
- 戦後60年の小泉談話全文 2005年8月15日
- chrome插件 时空隧道
- Hybrid App:借助HTML5、JavaScript和CSS3开发
- 为什么Scrum不行?
- svn merge branch
- 二分查找
- Javascript在页面的执行顺序
- Magic Potions
- JVM学习笔记
- android里面Canvas,save()与restore()。
- CSS padding margin border属性详解
- 数据结构 二路归并排序的实现
- poj 1032 拆分数字使乘积最大
- 九度oj 1058