前言

查找算法是一种用于在数据集合中查找特定元素的算法。在计算机科学中,查找算法通常被用于在数组、链表、树等数据结构中查找目标元素的位置或者判断目标元素是否存在。
查找算法的目标是在尽可能短的时间内找到目标元素,以提高程序的效率和性能。常见的查找算法包括但不限于二分查找、哈希表查找、线性查找、二叉查找树等。

一、查找算法预备知识

查找算法分类

1)静态查找和动态查找;
注:静态或者动态都是针对查找表而言的。动态表指查找表中有删除和插入操作的表。
2)无序查找和有序查找。
无序查找:被查找数列有序无序均可;
有序查找:被查找数列必须为有序数列。

平均查找长度(Average Search Length,ASL)
需和指定key进行比较的关键字的个数的期望值,称为查找算法在查找成功时的平均查找长度。
对于含有n个数据元素的查找表,查找成功的平均查找长度为:ASL = Pi*Ci的和。

Pi:查找表中第i个数据元素的概率。
Ci:找到第i个数据元素时已经比较过的次数。

二、分块查找

分块查找(Blocking Search)又称为索引顺序查找法,在此查找法中,除了原表本身以外还需要建立一个“索引表”,即将原表分成一块一块,每一块选取其最大的记录作为关键字项,块中的起始下标为块的指针项。索引表按照关键字有序,即块与块之间有序,块内元素无序。查找时先确定待查找的记录在哪一块,再在具体某个块内使用顺序查找法查找其具体位置。故其性能介于顺序查找法和折半查找法之间。

算法步骤

  • 首先确定待查记录所在的块(子表)
  • 然后在块中进行顺序查找确定记录的最终位置
public class BlockSearch {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        //原表
        int a[] = {9, 22, 12, 14, 35, 42, 44, 38, 48, 60, 58, 47, 78, 80, 77, 82};
        //分块获得对应的索引表,这里是一个以索引结点为元素的对象数组
        BlockTable[] arr = {
                new BlockTable(22, 0, 3),//最大关键字为22 起始下标为0,3的块
                new BlockTable(44, 4, 7),
                new BlockTable(60, 8, 11),
                new BlockTable(82, 12, 15)
        };
        //打印原表
        System.out.print("原表元素如下:");
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
        System.out.println();
        //待查关键字
        while (true) {
            System.out.print("请输入你所要查询的关键字:");
            int key = input.nextInt();
            //调用分块查找算法,并输出查找的结果
            int result = BlockSearch(a, arr, key);
            System.out.print("查询结果为:" + result);
            System.out.println();
        }
    }

    private static int BlockSearch(int a[], BlockTable[] arr, int key) {
        int left = 0, right = arr.length - 1;
        //利用折半查找法查找元素所在的块
        while (left <= right) {
            int mid = (left + right) >>> 1;
            if (arr[mid].key >= key) {
                right = mid - 1;
            } else {
                left = mid + 1;
            }
        }
        //循环结束,元素所在的块为right+1 取对应左区间下标作为循环的开始点
        int i = arr[right + 1].low;
        //在块内进行顺序查找确定记录的最终位置
        while (i <= arr[right + 1].high && a[i] != key) {
            i++;
        }
        //如果下标在块的范围之内,说明查找成功,佛否则失败
        if (i <= arr[right + 1].high) {
            return i;
        } else {
            return -1;
        }
    }
}

//索引表结点
class BlockTable {
    int key;
    int low;
    int high;

    BlockTable(int key, int low, int high) {
        this.key = key;
        this.low = low;
        this.high = high;
    }
}

在这里插入图片描述

三、总结

3.1 查找性能

时间、空间复杂度均不超过O(n)

3.2 适用场景

适用于静态查找表:即查找表不经常发生变化,适合建立分块索引。
适用于有序表:由于分块查找是基于有序表的,因此适用于有序表的查找。
数据量较大:当数据量较大时,分块查找可以将数据分块处理,提高查找效率。
查找频繁:如果需要频繁进行查找操作,分块查找可以提供较快的查找速度。

总的来说,分块查找结合了顺序查找和折半查找的优点,适用于静态、有序、数据量大且需要频繁查找的情况。它能够有效地减少查找时间,提高查找效率。

3.3 优缺点

优点:

在表中插入和删除元素时,只需要找到对应的块,就可以在块内进行插入和删除运算
块内无序,插入和删除都较为容易,无需进行大量移动
适合线性表既要快速查找又要经常动态变化的场景

缺点:

需要增加一个存储索引表的内存空间
需要对初始索引表按照其最大关键字(或最小关键字)进行排序运算

参考链接:
Java基本查找算法–分块查找

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐