查找算法
线性查找
定义:就是在一组数据(列表)中寻找一个某个值是否存在,并返回其存储位置的下标。查找算法最需要解决的问题是如果在最短时间内接近目标值。
线性查找:就是没有使用任何方法,直接从头到尾,逐一进行判断。但是由于暴力简单,所以不需要列表是否有序。
def lineSearch(arr,num):
flag = 0
for i in range(len(arr)):
if arr[i]==num:
flag=1
print("找到了,在第{}个位置".format(i+1))
if flag==0:
print("没有找到!")
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
lineSearch(arr,9000000-1)
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
二分查找
二分查找:必须保证被查找的数据是有序的。它的查找策略是:先判断中间值和目标值进行比较;若大于,则抛弃左边较小的一半数据;若小于,则抛弃右边较大的一半数据;若相等,则已经找到。二分查找对于有序数据的的时间效率为O(logn)。
def binarySearch(arr,left,right,findVal):
#定义一个数组储存下标,又可能存在多个相同元素
resIndex = []
#arr必须有序
mid = int((left+right)/2)
midVal = arr[mid]
if left>right:
return -1
if findVal > midVal:
return binarySearch(arr,mid+1,right,findVal)
elif findVal<midVal:
return binarySearch(arr,left,mid-1,findVal)
else:
temp = mid - 1
while(True):#左边
if temp>len(arr)-1 or arr[temp]!=findVal:
break
resIndex.append(temp+1)
temp-=1
resIndex.append(mid+1)#中间
temp=mid+1
while(True):#右边
if temp<0 or arr[temp]!=findVal:
break
resIndex.append(temp+1)
temp+=1
return resIndex
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
print("Index="+str(binarySearch(arr,0,len(arr),1)))
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
插值查找
插值查找:插值查找是在二分查找的基础进行了部分改进,所以它也需要被查找数据是有序的。它对于二分查找每次直接对中间=(left+right)/ 2 这个计算方式进行了改进。运用了数学分析的知识,把分割点改为 ** left + (right-left)*(int((findVal-arr[left])/(arr[right]-arr[left]))) **,不过在使用前需要先判断目标值是否大于数据的最大值或者小于数据的最小值,否则会有越界风险。
def insertSearch(arr,left,right,findVal):
#定义一个数组储存下标,又可能存在多个相同元素
resIndex = []
#arr必须有序
if left>right or findVal<arr[0] or findVal>arr[len(arr)-1]:
return -1
mid = left + (right-left)*(int((findVal-arr[left])/(arr[right]-arr[left])))
midVal = arr[mid]
if findVal > midVal:
return insertSearch(arr,mid+1,right,findVal)
elif findVal<midVal:
return insertSearch(arr,left,mid-1,findVal)
else:
temp = mid - 1
while(True):#左边
if temp>len(arr)-1 or arr[temp]!=findVal:
break
resIndex.append(temp+1)
temp-=1
resIndex.append(mid+1)#中间
temp=mid+1
while(True):#右边
if temp<0 or arr[temp]!=findVal:
break
resIndex.append(temp+1)
temp+=1
return resIndex
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
print("Index="+str(insertSearch(arr,0,len(arr)-1,1)))
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
斐波那契查找
斐波那契查找:看完以上两种查找方式,你发现查找算法就是对如何数据进行分隔并接近目标值的一种算法,而在数学上刚好有一种经典的分割方式——黄金分割0.618。而且黄金分割刚好和斐波那契数列有着数学上的关系。使用斐波那契数列的前一个数和后一个数进行除法,刚好会越来越接近黄金分割比例。由此我们产生了一种新的查找算法:斐波那契查找。
import copy
#arr = [1,8,10,89,1000,1234]
import time
arr = [0 for i in range(9000)]
for i in range(9000):
arr[i]=i
def fib():#非递归
f = [0 for i in range(9000)]
f[0]=1
f[1]=1
for i in range(2,9000,1):
f[i]=f[i-1]+f[i-2]
return f
def fibSearch(arr,key):
low = 0
high=len(arr)-1
k = 0 #分割数字的下标
mid = 0
f = fib()
#获取斐波那契分隔数的下标
while(high>f[k]-1):
k+=1
temp = copy.deepcopy(arr)
for i in range(high+1,f[k],1):
temp.append(arr[high])
while(low<=high):
mid = low+f[k-1]-1
if key<temp[mid]:#左边查找
high=mid-1
k-=1
elif key>temp[mid]:#右边查找
low=mid+1
k-=2
else:
if mid<=high:
return mid
else:
return high
return -1
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))
print("Index="+str(fibSearch(arr,11) ))
print(time.strftime("%Y-%m-%d %H:%M:%S",time.localtime()))