#include <iostream>
using namespace std;
typedef int KeyType;
//定义查找表
typedef struct {
KeyType key;
}ElemType;
typedef struct {
ElemType* data;
int length;
}SSTable;
//定义索引表与表内分块
typedef struct {
KeyType key; //块内最大键值
int stadr; //块起始地址
}indexItem;
typedef struct {
indexItem* data; //索引表基地址
int length; //索引表长度
}indexTable;
bool Create_IdxTable(SSTable& ST, indexTable& ID, int n, int t);//n代表查找表中元素个数,t代表每个索引块长度
int Search_Idx(SSTable ST, indexTable ID, KeyType kval);
bool Create_IdxTable(SSTable& ST, indexTable& ID, int n, int t){
ST.data = new ElemType[n + 1];
if (!ST.data) return 0;
cout << "请输入查找表元素:" << endl;
for (int i = 1; i <= n; i++)
cin >> ST.data[i].key;
ST.length = n;
int count = n / t; //计算块数
if (n % t != 0) count++;//将剩余数据单独放入一个块
ID.data = new indexItem[count];//构造索引表共count个块
if (!ST.data) return 0;
for (int i = 0; i < count; i++) {//遍历每一个块
int k;//用来记录每个块存储数据的实际长度
ID.data[i].stadr = i * t + 1;//查找表中第一个位置为空,因此首地址增1
if (ID.data[i].stadr + t < ST.length)//若未到达查找表末尾
k = ID.data[i].stadr + t - 1;
else//若已到达末尾,则长度就是查找表的长度
k = ST.length;
KeyType max = ST.data[ID.data[i].stadr].key;//设定初始的块内最大值
for (int j = ID.data[i].stadr + 1; j <= k; j++)//找出实际块内最大值
if (ST.data[j].key > max)
max = ST.data[j].key;
ID.data[i].key = max;
}
ID.length = count;
return true;
}
int Search_Idx(SSTable ST, indexTable ID, KeyType kval){
int low = 0, high = ID.length - 1; int mid = (low + high) / 2;
if (kval > ID.data[high].key) return 0; //kval大于所有关键字,查询结束
while (low <= high) {//折半查找索引表,确定记录查找区间
mid = (low + high) / 2;
if (kval < ID.data[mid].key) high = mid - 1;
else if (kval > ID.data[mid].key) low = mid + 1;
else { low == mid; break; }
}
//下一步的查找范围定位在第mid块
int stadr = ID.data[mid].stadr; //没啥用,太长了懒得写不好看,找个变量代替一下,是查找区间的下界
int top;//同理,查找区间的下界
if (mid < ID.length - 1)//若不是最后一个块
top = ID.data[mid + 1].stadr - 1;
else top = ST.length; //stard和top为在ST表进行查找的下界和上界
if (ST.data[stadr].key == kval) return stadr;
else { //在ST.data[stard] 至ST.data[top-1]的区间内进行顺序查找
ST.data[0] = ST.data[stadr]; //暂存ST.data[top]
ST.data[stadr].key = kval; //确保只在本块中寻找
int k;
for (k = top; ST.data[k].key != kval; k--);//k==stadr时必然结束
ST.data[stadr] = ST.data[0]; //恢复暂存值
if (k != stadr) return k; else return 0;
}
}
int main()
{
SSTable ST;
indexTable ID;
int n, i, t;
KeyType key;
cout << "请输入查找表中元素个数:" << endl;
cin >> n;
cout << "请输入索引块长度:" << endl;
cin >> t;
if (!Create_IdxTable(ST, ID, n, t)) {
cout << "查找表赋值失败" << endl;
return 1;
}
cout << "请输入要查找的元素关键字值:" << endl;
cin >> key;
i = Search_Idx(ST, ID, key);
if (i == 0)
cout << "未找到!" << endl;
else
cout << "找到,位序为" << i << endl;
return 0;
}
实验样例