基于线性表的查找算法
(1)顺序查找算法
- 用数组存储
- 按顺序查找关键字的位置
def seq_search(l,a):
l.index(a)
for i , k in enumerate(l):
if k==a:
return i
return -1
L=[2 ,5,2,6,8,6]
seq_search(L,3)
此代码与下代码同作用
L.index(5)
(2)折半查找算法
与折半插入排序算法思想差不多:
只能在有序的数组中查找
设给定的数组为A,元素为A[i],元素个数一共有n个,其中0<=i<=n-1
- 分别指向数列的第一位和末位,下标为low和highm = (low + high)/2
- 如果要插入的数小于m位置的数,说明要在低半区查找,high = m - 1
- 如果要插入的数大于m位置的数,说明要在高半区查找,low = m + 1
- 如果要插入的数等于m位置的数,直接退出,high=m
def halffind(l,a):
low = 0
high = len(l) - 1
mid = (low + high) // 2
while low <= high:
if l[mid] > a:
high = mid - 1
elif l[mid] < a:
low = mid + 1
else:
return mid
mid = (low + high) // 2
return -1
(3)插值查找算法
在折半查找的基础上多了:
- mid= (key-a[low])/(a[high]-a[low])*(high-low)
# 作者:沙振宇
# 时间复杂性:如果元素均匀分布,则O(log log n)),在最坏的情况下可能需要 O(n)。
# 空间复杂度:O(1)。
# 插值查找算法
def interpolation_search(list, key):
length = len(list)
low = 0
high = length - 1
time = 0
print("length:%s list:%s"%(length,list))
while low < high:
time += 1
# 计算mid值是插值算法的核心代码
mid = low + int((high - low) * (key - list[low]) / (list[high] - list[low]))
if key < list[mid]:
high = mid - 1
elif key > list[mid]:
low = mid + 1
else:
return mid
return False
if __name__ == '__main__':
list = [1, 5, 7, 8, 22, 54, 99, 123, 200, 222, 444]
result = interpolation_search(list, 444)
print("List key is:", result)
(4)分块查找算法
分块算法是在顺序查找法中的一个优化,基于一个已排序好的数组中做的查找。
- 时间复杂度:O(log(m)+N/m)
- 先选取各块中的最大关键字构成一个索引表
- 查找分两个部分:先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中
- 在已确定的块中用顺序法进行查找
# 二分查找
def binary_search(list, key):
length = len(list)
first = 0
last = length - 1
print("length:%s list:%s"%(length,list))
while first <= last:
mid = (last + first) // 2
if list[mid] > key:
last = mid - 1
elif list[mid] < key:
first = mid + 1
else:
return mid
return False
# 分块查找
def block_search(list, count, key):
length = len(list)
#############分块思想,分block_length个块分数据############
block_length = length//count
if count * block_length != length:
block_length += 1
print("block_length:", block_length) # 块的多少
for block_i in range(block_length):
block_list = []
for i in range(count):
if block_i*count + i >= length:
break
block_list.append(list[block_i*count + i])
#######################################################
result = binary_search(block_list, key)
if result != False:
return block_i*count + result
return False
if __name__ == '__main__':
list = [1, 5, 7, 8, 22, 54, 99, 123, 200, 222, 444]
result = block_search(list, 4, 444) # 第二个参数是块的长度,最后一个参数是要查找的元素
print("List key is:", result)
基于树的查找法
(1)二叉排序树(BST)
(2)二叉平衡树
斐波那契查找法
斐波那契查找就是在二分查找的基础上根据斐波那契数列进行分割的:
- 在斐波那契数列找一个等于略大于查找表中元素个数的数F[n],将原查找表扩展为长度为F[n](如果要补充元素;
- 则补充重复最后一个元素,直到满足F[n]个元素),完成后进行斐波那契分割,即F[n]个元素分割为前半部分F[n-1]个元素;
- 后半部分F[n-2]个元素,找出要查找的元素在那一部分并递归,直到找到。
# 斐波那契查找算法
def fibonacci_search(list, key):
length = len(list)
# 需要一个现成的斐波那契列表。其最大元素的值必须超过查找表中元素个数的数值。
F = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368]
low = 0
high = length - 1
print("length:%s list:%s"%(length,list))
# 为了使得查找表满足斐波那契特性,在表的最后添加几个同样的值
# 这个值是原查找表的最后那个元素的值
# 添加的个数由F[k]-1-high决定
k = 0
#找一个比数组长度大一点的元素
while high > F[k] - 1:
k += 1
i = high
##往数组后面添元素直到长度为F[k]-1,添加的都是数组最后一个元素
while F[k] - 1 > i:
list.append(list[high])
i += 1
time = 0 # 算法主逻辑。time用于展示循环的次数。
while low <= high:
time += 1
# 为了防止F列表下标溢出,设置if和else
if k < 2:
mid = low
else:
mid = low + F[k - 1] - 1
if key < list[mid]:
high = mid - 1
k -= 1
elif key > list[mid]:
low = mid + 1
k -= 2
else:
if mid <= high:
return mid
else:
return high
return False
if __name__ == '__main__':
list = [1, 5, 7, 8, 22, 54, 99, 123, 200, 222, 444]
result = fibonacci_search(list, 7)
print("List key is:", result)
高级数表查找算法
红黑树
B、B+树