顺序查找就是将数列从头到尾按照顺序查找一遍,只需遍历一遍列表,然后逐一判断,顺序查找是最容易理解,时间复杂度最高的排序方法(不需要事先排序)
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
def sequentialSearch(iList,key):
for i in range(len(iList)):
if iList[i] == key:
return i
return -1
if __name__ == '__main__':
iList = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
key = 10
res = sequentialSearch(iList,key)
print(res)
if res >= 0:
print('%d is in the list, index is: %d\n'%(key, res))
else:
print('%d is not in list'%key)
又称之为折半查找,一种计算复杂度为log(n)的查找方法,与线性查找相比,数量级越大,效率的优势越是明显。但是二分法查找的前提是“已经排序好的线性表”,也就是说,一维数组中的数据必须是已经排序好了,才能使用二分法来进行查找,排序方式没有影响。
1:首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。
2:如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤1的操作。
3:如果某一步数组为空,则表示找不到目标元素。
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from quickSort import quickSort # 从外部导入的快速排序算法
def binarySearch(iList, key):
iLen = len(iList)
left = 0 # 初始化左边界下标
right = iLen - 1 # 初始化右边界下标
while right > left: # 如果右边结的下标与左边下标相等则跳出循环
mid = (right+left) // 2
if key < iList[mid]: # 如果比中间的数小,则调整右边界为mid-1
right = mid - 1
elif key > iList[mid]: # 如果比中间的数大,则调整左边界mid+1
left = mid + 1
else: # 相等则返回
return mid
if key == iList[left]:
return left
elif key == iList[right]:
return right
else: # 如果到right > left还没找到,则证明列表中没有改元素
return -1
if __name__ == '__main__':
iList = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
iList = quickSort(iList) # 用快速排序给列表排序
key = 10
res = binarySearch(iList, key)
if res >= 0:
print('%d is in the list, index is: %d\n' % (key, res))
else:
print('%d is not in list' % key)
其原理跟二分法的原理很类似,依旧是在左右边界中间取一个特定的mid值,只不过与二分法的区别在于它的mid的取值不是取左右边界的下标均值,而是以mid = left + (key -iList[left])*(right-left) //(iList[right]-iList[left])数学式,其中的left,right分别表示左右边界的下标,值得注意的是,因为除以(iList[right]-iList[left])取整,所以iList[right]与iList[left]差值太大,mid的值会一直取left,从而陷入死循环。
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
from quickSort import quickSort # 从外部导入的快速排序算法
def insertSearch(iList, key):
"""
插值查找 (已测,效率比较低)
:param iList:
:param key:
:return:
"""
iLen = len(iList)
left = 0
right = iLen - 1
while right > left:
mid = left + (key - iList[left])*(right-left) // (iList[right]-iList[left])
if mid == left:
mid += 1 # 当iLis[right] 与 iList[left]相差太大是时,有可能导致mid一直等于left,从而陷入死循环
if key < iList[mid]:
right = mid -1
elif key > iList[mid]:
left = mid + 1
else:
return mid
if key == iList[left]:
return left
elif key == iList[right]:
return right
else:
return -1
if __name__ == '__main__':
iList = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
iList = quickSort(iList) # 用快速排序给列表排序
key = 10
res = insertSearch(iList, key)
if res >= 0:
print('%d is in the list, index is: %d\n' % (key, res))
else:
print('%d is not in list' % key)
分块查找首先按照一定的取值范围将数列分成数块,块内的元素可以是无序的,但块必须是有序的(处于后面位置的块的最小元素要比前一个块的最大元素大),在分块完成后,再确定key值(需要查找的值)所处与块的区间,最后用顺序排序法逐一比对。
# -*- coding:utf-8 -*-
"""
Author: leadingme
Mail:[email protected]
MyWebsite:leadingme.top
"""
iList = [7, 5, 9, 3, 5, 1, 12, 10, 15, 9]
indexList = [[5,0],[10,0],[15,0],[20,0]]
def divideBlock():
global iList, indexList
sortList = [] # 用来存放分块好后的新列表
for key in indexList:
subList = [] # 定义一个列表,用来存放每一块的元素
for i in iList:
if i < key[0]:
subList.append(i)
for j in subList: # 过滤掉已经加入到subList中的元素
iList.remove(j)
key[1] = len(subList)
sortList += subList
iList = sortList
return indexList
def blockSearch(iList, indexList, key):
left = 0 # 搜索数列的起始点索引
right = 0 # 搜索数列的终点索引
for indexInfo in indexList: # 确定key所在的块级
left += right
right += indexInfo[1]
if key < indexInfo[0]:
break
for i in range(left, right):
if key == iList[i]:
return i
return -1
if __name__ == '__main__':
indexList = divideBlock()
print(indexList)
print(iList)
key = 7
res = blockSearch(iList, indexList, key)
if res >= 0:
print('%d is in the list, index is: %d\n' % (key, res))
else:
print('%d is not in list' % key)