图解算法-使用python
学习笔记(4)
查找与哈希算法
哈希法又可称为散列法
常见的查找算法有:顺序查找、二分查找、插值查找。
其中插值查找法又叫插补查找法,是二分查找的改进版。按照数据的分布,利用公式预测数据所在的位置,再以二分法的方式逐渐逼近。
import random
def interpolation_search(data, val):
low = 0
high = 49
print('查找过程中......')
while low <= high and val != -1:
mid = low + int((val - data[low]) * (high - low) / (data[high] - data[low])) # 插值查找法公式
if val == data[mid]:
return mid
elif val < data[mid]:
print('%d 介于位置 %d[%3d] 和中间值 %d[%3d] 之间,找左半边' \
% (val, low + 1, data[low], mid + 1, data[mid]))
high = mid - 1
elif val > data[mid]:
print('%d 介于中间值位置 %d[%3d] 和 %d[%3d] 之间,找右半边' \
% (val, mid + 1, data[mid], high + 1, data[high]))
low = mid + 1
return -1
val = 1
data = [0] * 50
for i in range(50):
data[i] = val
val = val + random.randint(1, 5)
while True:
num = 0
val = int(input('请输入查找键值(1-150),输入-1结束:'))
if val == -1:
break
num = interpolation_search(data, val)
if num == -1:
print('##### 没有找到[%3d] #####' % val)
else:
print('在第 %2d个位置找到 [%3d]' % (num + 1, data[num]))
print('数据内容为:')
for i in range(5):
for j in range(10):
print('%3d-%-3d' % (i * 10 + j + 1, data[i * 10 + j]), end='')
print()
常见的哈希法简介
除留余数法:将数据除以某一个常数后,取余数来当索引。
平方取中法:先计算数据的平方,之后再去中间的某段数字作为索引。
折叠法:将数据转换成一串数字后,先将这串数字拆成几个部分,再把它们加起来,就可以计算出这个键值的Bucket Address(桶地址)
数字分析法:简单来讲就是将不会改变的数据,取不重合且适当的数字做成索引表。
碰撞与溢出解决
线性探测法:当发生碰撞情况时,若该索引对应的存储位置已有数据,则以线性的方式往后找空的存储位置,一旦找到就把数据放进去。
import random
INDEXBOX=10 #哈希表最大元素
MAXNUM=7 #最大数据个数
def print_data(data,max_number): #打印数组子程序
print('\t',end='')
for i in range(max_number):
print('[%2d] ' %data[i],end='')
print()
def create_table(num,index): #建立哈希表子程序
tmp=num%INDEXBOX #哈希函数 = 数据%INDEXBOX
while True:
if index[tmp]==-1: #如果数据对应的位置是空的
index[tmp]=num #则直接存入数据
break
else:
tmp=(tmp+1)%INDEXBOX #否则往后找位置存放
#主程序
index=[None]*INDEXBOX
data=[None]*MAXNUM
print('原始数组值:')
for i in range(MAXNUM): #起始数据值
data[i]=random.randint(1,20)
for i in range(INDEXBOX): #清除哈希表
index[i]=-1
print_data(data,MAXNUM) #打印起始数据
print('哈希表的内容:')
for i in range(MAXNUM): #建立哈希表
create_table(data[i],index)
print(' %2d =>' %data[i],end='') #打印单个元素的哈希表位置
print_data(index,INDEXBOX)
print('完成的哈希表:')
print_data(index,INDEXBOX) #打印最后完成的结果
平方探测法:当发生溢出时,下一次查找的地址是(f(x)+i^2)mod B与(f(x)-i^2)mod A
再哈希法:是一开始就先设置一系列的哈希函数,如果第一种哈希函数出现溢出时就改用第二种,以此类推。