15 基本查找算法:顺序查找与分块查找
2020-02-18 本文已影响0人
GoFuncChan
一、顺序查找算法
在基于线性表查找的算法中,顺序查找是最简单的,基本思想就是暴力枚举查找。
顺序查找法的特点是逐一比较指定的关键字与线性表中各个元素的关键字,一直到查找成功或失败为止。
说明:
顺序查找适合于存储结构为顺序存储或链接存储的线性表。
基本思想:
顺序查找也称为线形查找,属于无序查找算法。从数据结构线形表的一端开始,顺序扫描,依次将扫描到的结点关键字与给定值k相比较,若相等则表示查找成功;
若扫描结束仍没有找到关键字等于k的结点,表示查找失败。
复杂度分析:
查找成功时的平均查找长度为:(假设每个数据元素的概率相等) ASL = 1/n(1+2+3+…+n) = (n+1)/2 ;
当查找不成功时,需要n+1次比较,时间复杂度为O(n);
所以,顺序查找的时间复杂度为O(n)。
使用环境:
有时你需要在集合中定位元素。你也许不得不在一个未知是否有序的集合中频繁地查找元素。当无法知道集合中更多的信息时,顺序查找能够以穷举的方式完成这个工作。
如果集合只能通过迭代器来存取,并且一次只能返回集合中的一个元素,那么顺序查找就是你能使用的唯一查找算法。
Go语言描述
// 顺序查找某个值的key
func SequenceSearch(arr []int, i int) int {
for k, v := range arr {
if v == i {
return k
}
}
return -1
}
分块查找算法
分块查找又称索引顺序查找,它是顺序查找的一种改进方法。
分块查找由于只要求索引表是有序的,对块内节点没有排序要求,因此特别适合于节点动态变化的情况。
算法思想:
将n个数据元素”按块有序”划分为m块(m ≤ n)。每一块中的结点不必有序,但块与块之间必须”按块有序”;
即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;
而第2块中任一元素又都必须小于第3块中的任一元素,……
算法流程:
step1 先选取各块中的最大关键字构成一个索引表;
step2 查找分两个部分:先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中;然后,在已确定的块中用顺序法进行查找。
Go语言描述
// 单个分块的结构体
type bIndex struct {
start int // 块开始索引
length int // 块长度
max int // 块最大值
}
/*
arr 满足分块查找的数组
bs 分块信息数组
val 查找的值
*/
func BlockSearch(arr []int, bs []bIndex, val int) int {
// 先找到所属块
var bi bIndex
for _, b := range bs {
if b.max > val {
bi = b
break
}
}
// 再在该块中查找该元素
for k, v := range arr[bi.start : bi.start+bi.length] {
if v == val {
return bi.start + k
}
}
return -1
}
运行测试:
func TestBlockSearch(t *testing.T) {
// 先构建符合条件的数组和分块
blockSlice := []int{3, 4, 6, 2, 5, 7, 14, 12, 16, 13, 19, 17, 25, 21, 36, 23, 22, 29}
indices := make([]bIndex, 3)
indices[1] = bIndex{start: 0, length: 6, max: 7}
indices[1] = bIndex{start: 6, length: 6, max: 19}
indices[1] = bIndex{start: 12, length: 6, max: 36}
i := BlockSearch(blockSlice, indices, 21)
j := BlockSearch(blockSlice, indices, 1)
t.Logf("BlockSearch:%v, existVal:21,existIndex:%d, noExistVal:1,noExistIndex:%d", blockSlice, i, j)
}
// === RUN TestBlockSearch
// --- PASS: TestBlockSearch (0.00s)
// search_test.go:60: BlockSearch:[3 4 6 2 5 7 14 12 16 13 19 17 25 21 36 23 22 29], existVal:21,existIndex:13, noExistVal:1,noExistIndex:-1
//PASS