查找算法-分块算法
查找算法主要有三种:
线性查找、二分查找、分块查找
线性查找效率最慢,可对无序列表进行查找、
二分查找效率最快,只能针对有序列表进行查找
分块查找的效率在线性查找和二分查找之间,可对无序列表进行查找。
分块查找的思路:
分块查询中,每个块中元素不一定有序的,块间是有序的。
分块又称索引顺序查找,这是顺序查找的一种改进方法,用于在分块有序表中进行查找 。
主表:存储数据的表,长度n;
索引表:将主表分块,每块长s,找出每块中的关键字最大值,并且保存该块中所有数据在主表中的索引
(1)分块:将n个数据元素“按块有序”划分为m块。
每一块中的结点不必有序,但块与块之间必须“按块有序”;即第1块中任一元素的关键字都必须小于第2块中任一元素的关键字;而第2块中任一元素又都必须小于第3块中的任一元素。每个块中元素不一定是有序的。
(2)根据查找值,和索引表中关键字(每块中的最大关键字)比较,通过对分查找/顺序查找,找到该值所在的块范围;
(3)在相应块中,找到该值在主表中的位置。
针对有序数组的分块查找代码实现:
#import <Foundation/Foundation.h>
struct indexBlock //定义块的结构
{
int key;
int start;
int end;
} indexBlock[4]; //定义结构体数组
int main(int argc, const char * argv[])
{
@autoreleasepool {
int j = -1, k, x;
int a[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
printf("已知有一组数:\n");
for (int i = 0; i < 15; i++) {
printf("%d ", a[i]);
}
printf("\n");
for (int i = 0; i < 3; i++) {
indexBlock[i].start = j + 1; //确定每个块范围的起始值
j = j + 1;
indexBlock[i].end = j + 4; //确定每个块范围的结束值
j = j + 4;
indexBlock[i].key = a[j]; //确定每个块范围中元素的最大值
}
printf("请输入你要查找的数:\n");
scanf("%d", &x);
k = blockSearch(x, a);
if (k >= 0) {
printf("查找成功!你要查找的数在数组中的位置是:%d\n", k+1);
}
else{
printf("查找失败!你要查找的数不在数组中。\n");
}
}
return 0;
}
int blockSearch(int x, int a[]){
int i = 0;
int j;
while (i<3 && x>indexBlock[i].key) { //确定在哪个块中
i++;
}
if (i >= 3) { //大于分的块数,则返回-1,找不到该数
return -1;
}
j = indexBlock[i].start; //j等于块范围的起始值
while (j<=indexBlock[i].end && a[j]!=x) { //在确定的块内进行查找
j++;
}
if (j > indexBlock[i].end) { //如果大于块范围的结束值,则说明没有要查找的数,j置为-1
j = -1;
}
return j;
}