查找算法 分享3:分块查找

秘诀:先分块,再匹配。分而治之

步骤:

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.因为块内记录的存放是任意的,所以插入或删除比较容易,无须移动大量记录。

缺点:分块查找算法的主要代价是增加一个辅助数组的存储空间。 

 补充:

#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

原文地址:https://www.cnblogs.com/hanjun/p/2892826.html