秘诀:先分块,再匹配。分而治之
感谢大神~~~
http://www.cnblogs.com/hanjun/archive/2013/02/05/2892826.html
话说第一个链接是小朋友学编程的讲解,不过确实通俗易懂,先看它入门,然后看第二个链接理解
不过逗逗帮你们总结啦~~
葫芦娃兄弟一共七人,为了避免穷举法可能遇到的最倒霉的情况,最后一个是大娃的话耗时就太长了。
我们可以使用分块查找法,在葫芦娃来的时候就将他们分成三个小块。第一块是大娃和二娃,第二块是三娃和四娃,第三块是五娃、六娃和七娃。在这三个小组里葫芦娃们并不需要按顺序排队。
块分好后,就可以寻找大娃了。我们取第二个块的第一个娃与大娃比较。第二个块的第一个娃是四娃,比大娃小。继续与第二个娃比较,第二个是三娃,一样比大娃小。
因为在搜索之前我们分块的时候做到了第二个块里的任意一个娃都比第一个块里的任意一个娃小,也就是第一个块里的最小的娃比第二个块里的最大的娃大。
我们可以确定的是大娃一定在第一个块里。再用穷举法穷举第一个块里的娃查找的大娃。
分块查找步骤:
1.先取各块中的最大关键字构成一个索引表。
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;
分块查找的优点:
1.在表中插入或删除一个记录时,只要找到该记录所属的块,就在该块内进行插入和删除运算。
2.因为块内记录的存放是任意的,所以插入或删除比较容易,无须移动大量记录。
缺点:分块查找算法的主要代价是增加一个辅助数组的存储空间。
例:已知有一组数
146 219 254 315 336 | 358 795 876 951 999 | 12 25 33 36 57
newIndex[0].start = 0
newIndex[0].end = 4
newIndex[0].key = 336
newIndex[1].start = 5
newIndex[1].end = 9
newIndex[1].key = 999
newIndex[2].start = 10
newIndex[2].end = 14
newIndex[2].key = 57
请输入您想要查找的数:
999
查找成功!您要找的数在数组中的位置是:10