秘诀:先分块,再匹配。分而治之
步骤:
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;
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.因为块内记录的存放是任意的,所以插入或删除比较容易,无须移动大量记录。
缺点:分块查找算法的主要代价是增加一个辅助数组的存储空间。
补充:
#include <stdio.h> struct index { //定义块的结构 int key; int start; int end; } newIndex[4]; //定义结构体数组 int search(int key, int a[]); int main(int argc, const char * argv[]) { //输出已知数组 int i, j=-1, k, key; int a[] = {146,219,254,315,336, 358,795,876,951,999, 12,25,33,36,57}; printf("已知有一组数\n"); for (i=0; i<15; i++) { printf("%d ",a[i]); if ((i+1)%5==0 && i<14) { printf(" | "); } } printf("\n\n"); //确认模块的起始值和最大值 for (i=0; i<3; i++) { newIndex[i].start = j+1; //确定每个块范围的起始值 j++; newIndex[i].end = j+4; //确定每个块范围的结束值 j += 4; newIndex[i].key = a[j]; //确定每个块范围中元素的最大值 printf("newIndex[%d].start = %d\n",i, newIndex[i].start); printf("newIndex[%d].end = %d\n",i, newIndex[i].end); printf("newIndex[%d].key = %d\n\n",i, newIndex[i].key); } //输入要查询的数,并调用函数进行查找 printf("请输入您想要查找的数:\n"); scanf("%d", &key); k = search(key, a); //输出查找的结果 if (k>0) { printf("查找成功!您要找的数在数组中的位置是:%d\n",k+1); }else{ printf("查找失败!您要找的数不在数组中。\n"); } return 0; } int search(int key, int a[]){ int i, startValue; i = 0; while (i<3 && key>newIndex[i].key) { //确定在哪个块中,遍历每个块,确定key在哪个块中 i++; } if (i>=3) { //大于分得的块数,则返回0 return -1; } startValue = newIndex[i].start; //startValue等于块范围的起始值 while (startValue<=newIndex[i].end && a[startValue]!=key) { //在确定的块内进行查找 startValue++; } if (startValue>newIndex[i].end) { //如果大于块范围的结束值,则说明没有要查找的数,startValue置为0 startValue = -1; } return startValue; }
已知有一组数
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