基础算法-查找:线性索引查找(II)
索引查找是在索引表和主表(即线性表的索引存储结构)上进行的查找。
索引查找的过程是:
1)首先根据给定的索引值K1,在索引表上查找出索引值等于K1的索引项,以确定对应子表在主表中的开始位置和长度。
2)然后再根据给定的关键字K2,在对应的子表中查找出关键字等于K2的元素(结点)。
对索引表或子表进行查找时,若表是顺序存储的有序表,则既可进行顺序查找,也可进行二分查找,否则只能进行顺序查找。
一提到“索引”,估计大家第一反应就是“数据库索引”,对的,其实主键建立“索引”,就是方便我们在海量数据中查找。
实现索引查找时常使用的三个术语:
1)主表:这个很简单,要查找的对象,主表在逻辑上被划分为一个一个的子表。
2)索引项:一般我们会用函数将一个主表划分成几个子表,每个子表建立一个索引,这个索引叫做索引项。
3)索引表:索引项的集合也就是索引表。
一般“索引项”包含三种内容:index,start,length
第一:index,也就是索引指向主表的关键字。
第二:start,也就是index在主表中的位置。
第三:length, 也就是子表的区间长度。
下面做一个有关分块索引的实现:
在主表中有10000个数据,现在分成100个子表,每个子表有100条记录,整个索引表有100个索引项对应100个子表。
对于某个子表,把它的所有记录中的最大项作为它对应的索引项的index。
在存储数据的时候,每个子表都有各自的数值的范围,插入一个新的数据时,先找到其要存储的位置(在那张子表中存储),然后查看这张子表是否有剩余的空间,如果有剩余的空间,插入该值然后更新对应的索引项。
程序代码实现
const int MaxSize = 10000; const int IndexItemNum = 100; //定义主表 struct student_info { int score; //some other attributes }; typedef struct student_info mainTable[MaxSize]; //定义索引表 struct indexItem { int index; int start; int length; }; typedef struct indexItem indexTable[IndexItemNum]; class IndexSearch { public: IndexSearch(); //在主表中添加一个元素,添加后返回它的下标,失败后返回-1 int addElements(int key); //返回搜索值在主表中的下标,如果检索失败返回-1 int searchElements(int key); private: indexTable index_table; mainTable main_table; //索引表中索引项的个数 const int indexItem_num; //每个子表存储的数据的个数 const int numPerBlock; };
上述代码定义了主表和索引表,同时确定了主表分成多少个子表和每个子表中存储数据的个数。
#include "IndexSearch.h" int IndexSearch::searchElements(int element) { int i,j; //检索索引表 int low = 0; int high = indexItem_num - 1; while(low <= high) { int mid = (low +high) / 2; if(element > index_table[mid].index) { low = mid + 1; } else if(element < index_table[mid-1].index) { high = mid - 1; } else { i = mid;//用i暂存结果 break; } }//while if(low > high) { return -1; //检索失败 } //检索主表 low = index_table[i].start; high = index_table[i].start + index_table[i].length; for(j = low; j < high; j++) { if(main_table[j].score == element) { break; } }//for if(j < high) { return j; } else { return -1; } } int IndexSearch::addElements(int element) { int tag = element / numPerBlock; if(tag > numPerBlock - 1) { tag = numPerBlock - 1; } if(index_table[tag].length < numPerBlock) { int start = index_table[tag].start; int length = index_table[tag].length; main_table[start + length].score = element; index_table[tag].length++; if(element > index_table[tag].index) { index_table[tag].index = element; } return start + length; } else { return -1; } } IndexSearch::IndexSearch(): indexItem_num(IndexItemNum), numPerBlock(100) { int index = 0; int start = 0; for(int i = 0; i < 100; i++) { index_table[i].length = 0; index_table[i].index = index; index_table[i].start = start; index += 100; start += 100; }//for }
初始化子表的个数和每个子表中存储数据的个数,同时实现插入和查找这两个函数。
测试代码:
#include <iostream> #include <ctime> #include "IndexSearch.h" using namespace std; void main() { srand(time(0)); IndexSearch searchTool; int index; int key; for(int i = 0; i < 1000; i++) { key = rand()%10000; index = searchTool.addElements(key); cout << "the number: " << key << " is insert in " << index << endl; } index = searchTool.addElements(2015); cout << "the number 2015: "<< " is insert in " << index << endl; //查找刚才插入的这个值 cout << "the number 2015 is stored is the position of "<< searchTool.searchElements(2015) << endl; index = searchTool.addElements(467); cout << "the number 467: "<< " is insert in " << index << endl; //查找刚才插入的这个值 cout << "the number 467 is stored is the position of "<< searchTool.searchElements(467) << endl; }