分块查找!

分块查找:

要将数据分成n多小块

在分块的时候要遵循两个原则:

  1. 前一块中的最大数据,小于后一块中所有的数据(块内无序,块间有序)

  2. 块的数量一般等于数字的个数开根号。比如:16个数字一般要分成4块

    7,10,      13,19,16,20 ,     27,22,30,40,36     ,43,50,48

核心思路:

先确定要查找的元素在哪一块,然后在块内挨个查找

package com.ZFJ.test1;
​
public class BasicSearchDemo1 {
    public static void main(String[] args) {
//        int[] arr={7,10,13,19,16,20,27,22,30,40,36,43,50,48};
        int[] arr = {7, 10,
                13, 19, 16, 20,
                27, 22, 30, 40, 36,
                43, 50, 48};
        //创建4个块的对象
        Block b1 = new Block(10, 0, 1);
        Block b2 = new Block(20, 2, 5);
        Block b3 = new Block(40, 6, 10);
        Block b4 = new Block(50, 11, 13);
​
        Block[] blockArr = {b1, b2, b3, b4};
        //定义变量记录要查找的数字
        int number = 13;
        //调用方法,传递索引表,数组,要查找的元素
        int index = blockSearch(blockArr, arr, number);
        //打印index
        System.out.println(index);
    }
    //利用分块查找的原理,查询number的索引
    private static int blockSearch(Block[] blockArr, int[] arr, int number) {
        //number在哪一块
        int indexBlock = findIndexBlock(blockArr, number);
        if (indexBlock == -1) {
            return -1;
        }
        //获取这一块当中的起始索引和结束索引
        int left = blockArr[indexBlock].getStartIndex();
        int right = blockArr[indexBlock].getEndIndex();
        //开始遍历,注意:二分查找要求数据是有序的,所以在这里不可以使用二分查找,因为块间有序,块内无序
        //用顺序遍历查找 
        for (int i = left; i <= right; i++) {
            if (number == arr[i]) {
                return i;
            }
        }
        return -1;
    }
​
    //定义一个方法,确定number在哪一块当中
    public static int findIndexBlock(Block[] blockArr, int number) {
        //从0索引开始遍历blockArr,如果number小于blockArr[i].getMax(),就表示number在这一块当中
        for (int i = 0; i < blockArr.length; i++) {
            if (number <= blockArr[i].getMax()) {
                return i;
            }
        }
        return -1;
    }
}
​
class Block {
    private int max;
    private int startIndex;
    private int endIndex;
​
    public Block() {
    }
​
    public Block(int max, int startIndex, int endIndex) {
        this.max = max; //最大值
        this.startIndex = startIndex;   //起始索引
        this.endIndex = endIndex;   //结束索引
    }
​
    public int getMax() {
        return max;
    }
​
    public void setMax(int max) {
        this.max = max;
    }
​
    public int getStartIndex() {
        return startIndex;
    }
​
    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }
​
    public int getEndIndex() {
        return endIndex;
    }
​
    public void setEndIndex(int endIndex) {
        this.endIndex = endIndex;
    }
}

扩展的分块查找(无规律的数据):

比如: 27, 22, 30, 40, 36, 13, 19, 16, 20, 7, 10, 43, 50, 48

在分块的时候要遵循一个原则:

每一块的数据范围不能有交集

我们就可以 27, 22, 30, 40, 36 ,    13, 19, 16, 20    , 7, 10,    43, 50, 48

而且要改变块内属性:

class Block{
    int min;    //块内最小值
    int max;    //块内最大值
    int startIndex;     //块内起始索引
    int endIndex;       //块内结束索引
}

记得要定义完整javabean类!

完整代码实现:

package com.ZFJ.test1;
​
public class BasicSearchDemo1 {
    public static void main(String[] args) {
        int[] arr = {27, 22, 30, 40, 36,
                13, 19, 16, 20,
                7, 10,
                43, 50, 48};
        //创建块的对象
        Block b1 = new Block(22, 40, 0, 4);
        Block b2 = new Block(13, 20, 5, 8);
        Block b3 = new Block(7, 10, 9, 10);
        Block b4 = new Block(43, 50, 11, 13);
        //添加到索引表中
        Block[] blockArr = {b1, b2, b3, b4};
        //定义变量记录要查找的数字
        int number = 48;
        //调用方法,传递索引表,数组和要查找的数字
        int index = getIndex(blockArr, arr, number);
        //打印索引
        System.out.println(index);
    }
    //根据分块查找的原理(先查找元素在哪一块,再在块内查找元素),查找number的索引
    private static int getIndex(Block[] blockArr, int[] arr, int number) {
        //number在哪一块
        int blockIndex = findIndexBlock(blockArr, number);
        //找不到返回-1
        if (blockIndex == -1) {
            return -1;
        }
        //块内起始索引
        int left = blockArr[blockIndex].getStartIndex();
        //块内结束索引
        int right = blockArr[blockIndex].getEndIndex();
        //在块内顺序查找元素
        for (int i = left; i <= right; i++) {
            if (arr[i] == number) {
                return i;
            }
        }
​
        return 0;
    }
​
    private static int findIndexBlock(Block[] blockArr, int number) {
        //查找元素在哪一块
        for (int i = 0; i < blockArr.length; i++) {
            if (number >= blockArr[i].getMin() && number <= blockArr[i].getMax()) {
                return i;
            }
        }
        return -1;
    }
​
}
​
class Block {
    private int min;    //块内最小值
    private int max;    //块内最大值
    private int startIndex; //块内起始索引
    private int endIndex;   //块内结束索引
​
    public Block() {
    }
​
    public Block(int min, int max, int startIndex, int endIndex) {
        this.min = min;
        this.max = max;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }
​
    public int getMin() {
        return min;
    }
​
    public void setMin(int min) {
        this.min = min;
    }
​
    public int getMax() {
        return max;
    }
​
    public void setMax(int max) {
        this.max = max;
    }
​
    public int getStartIndex() {
        return startIndex;
    }
​
    public void setStartIndex(int startIndex) {
        this.startIndex = startIndex;
    }
​
    public int getEndIndex() {
        return endIndex;
    }
​
    public void setEndIndex(int endIndex) {
        this.endIndex = endIndex;
    }
}
​
​
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值