开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情
顺序查找效率太低,而二分查找条件严格。能否有一种算法,折合两种优点呢?
1.分块查找概念
1.分块查找
先将线性表分块,然后实行“块间二分查找,块内顺序查找”。
2.适用条件
按块有序,块内任意。每一块内的元素不需要有序,但块与块之间是按键值有序的。即第i块中所有元素的键值都必须小于第j块中的所有元素
2.分块查找实现
1.分块查找步骤
1.块定位:确定所查找元素可能属于的块,可以通过二分查找实现
2.块内查找:建立一个块索引表,块索引表中包含每一块的相关信息。通常将块中的最大值作为该块的键值代表
2.建立块索引表
第一种类型:基于顺序表,每块的长度不同,在块索引表中记录每一块的起点和终点,这种类型适用于静态查找,因为在一块中进行插入和删除操作时都会影响到其后继块的块索引信息
第二种类型:基于顺序表,每块的长度相同,在块索引表中记录每一块的起点和实际元素的个数,每块都可能有一些空闲的位置,因此这种类型可实现有限的动态查找,即在每一块没有填满前都可以向该快中插入数据,而对一块中元素的删除操作只对本块中的元素有影响
第三种类型:基于链表,在块索引中记录每块的第一个结点的地址和键值。适用于动态查找,对主表进行插入和删除操作时,只对所操作的块中的结点有影响
3.分块查找表类型定义
#define M 6//分块数的上限
struct bitNode {//块索引表的元素类型定义
int mkey;//键值代表
int begin, end;//块的起点下标和终点下一个元素的下标
bool operator<(const bitNode bit)const {
return mkey < bit.mkey;
}
};
struct bitTable {//分块查找表
bitNode bit[M];//块索引表
int sz;//分块的实际数量
vector<int>sl;//原始顺序表
bitTable():sz(0){}
};
4.分块查找算法
功能:给定分块查找表b,查找是否存在键值为k的元素
步骤
(1)利用二分查找法在b.bit中确定k所在的块的块号i
(2)在第i块中利用顺序查找法确定是否存在键值为k的元素
代码
#include<iostream>
#include<vector>
using namespace std;
#define M 6//分块数的上限
struct bitNode {//块索引表的元素类型定义
int mkey;//键值代表
int begin, end;//块的起点下标和终点下一个元素的下标
bool operator<(const bitNode bit)const {
return mkey < bit.mkey;
}
};
struct bitTable {//分块查找表
bitNode bit[M];//块索引表
int sz;//分块的实际数量
vector<int>sl;//原始顺序表
bitTable():sz(0){}
};
//对分块查找表b进行分块查找,查找的键值为k,查找成功,返回k在原顺序表中的下标,否则返回-1
int block_search(bitTable b, int k) {
bitNode bit1;
bit1.mkey = k;
int i = lower_bound(b.bit, b.bit + b.sz, bit1) - b.bit;//i为键值k所在的块
if (i >= b.sz)return -1;//k比所有键值都大,查找失败
bitNode bit = b.bit[i];//第i个块的块索引表
vector<int>sl(b.sl);//原始顺序表
for (int j = bit.begin; j < bit.end; j++)//在第i个块内进行顺序查找
if (sl[j] == k)return j;//查找成功
return -1;
}
//构建原始数据和块索引表b
void get_bitTable(bitTable& b) {
int k, mk;
int i, n = 0, m;
cout << "输入分块数量:";
cin >> m;
b.sz = m;
for (i = 0; i < m; i++) {
cout << "输入第" << i + 1 << "块的键值(当输入0时结束本块输入):" << endl;
b.bit[i].begin = n, mk = -1;//n为当前原始数据的下标
while (cin >> k, k > 0) {//假设键值都为正
b.sl.push_back(k);//将键值依次加入原始顺序表
if (mk < k)mk = k;//更新当前块的最大值
++n;
}
b.bit[i].mkey = mk;
b.bit[i].end = n;//第i+1块索引表构建完毕
}
}
int main() {
bitTable b;
get_bitTable(b);
cout << block_search(b, 9) << endl;//查询9在表中的位置
}
5.优缺点
分块查找的速度不如折半查找算法,但比顺序查找算法快,同时又不需要对键值表进行排序