插值搜素是对实例二分搜索的改进.其中排序数组中的值是均匀分布的.二分搜索总是对中间元素进行检查.插值搜索可能会根据正在搜索的键的值去查找不同的位置.如果键的值更接近最后一个元素.则插值搜索很可能会向末端一侧开始搜索.
1.步骤:
1.1:从列表中间开始搜索数据.
1.2:如果匹配.则返回元素索引.然后退出.
1.3:如果不匹配则预测位置.
1.4:使用预测公式划分列表并找到新的中间点.
1.5:如果数据大于中间值.则在更高的子列表中搜索.
1.6:如果数据小于中间值.则在较低的子列表中搜索.
1.7:重复以上步骤直到匹配.
2.使用场景:
有序和均匀分布的数据:
插值搜索算法在搜索均匀分布的有效数据集中的元素时很有效.因为插值公式依赖于此属性进行准确的预测.
近似匹配:
插值搜搜算法在搜素近似匹配时很有用.因为它会在数据集中找到最接近的目标元素.
3.实现:
3.1方法:
package data
func InterpolationSearch(array []int, key int) int {
min, max := array[0], array[len(array)-1]
low, high := 0, len(array)-1
for {
if key < min {
return low
}
if key > max {
return high + 1
}
//预测位置.
var guess int
if high == low {
guess = high
} else {
size := high - low
offset := int(float64(size-1) * (float64(key-min) / float64(max-min)))
guess = low + offset
}
if array[guess] == key {
//如果预测值出现多次.
for guess > 0 && array[guess-1] == key {
guess--
}
return guess
}
if array[guess] > key {
high = guess - 1
max = array[high]
} else {
low = guess + 1
min = array[low]
}
}
}
3.2main方法:
func main() {
array := []int{1, 6, 8, 22, 23, 33, 55, 66, 99}
search := data.InterpolationSearch(array, 33)
fmt.Println(search)
}
4.实战:
给定一个有序的整数数组和一个目标值.使用插值搜索算法确定目标值是否存在.如果存在则返回索引.
4.1方法:
func InterpolationSearch2(array []int, n, target int) int {
if n == 0 {
return -1
}
low := 0
high := n - 1
for array[high] != array[low] && target >= array[low] && target <= array[high] {
//预估中间值.
mid := low + ((target - array[low]) * (high - low) / (array[high] - array[low]))
//找到目标值.
if target == array[mid] {
return mid
} else if target < array[mid] {
high = mid - 1
} else {
low = mid + 1
}
}
if target == array[low] {
return low
} else {
return -1
}
}
4.2main方法:
func main() {
array := []int{2, 5, 6, 8, 9, 10}
target := 5
n := len(array)
index := data.InterpolationSearch2(array, n, target)
if index == -1 {
fmt.Println("没有找到元素.")
} else {
fmt.Println("元素索引为", index)
}
}
山也青水也秀.情也深意也重.
如果大家喜欢我的分享的话.可以关注我的微信公众号
念何架构之路