分块查找:
要将数据分成n多小块
在分块的时候要遵循两个原则:
-
前一块中的最大数据,小于后一块中所有的数据(块内无序,块间有序)
-
块的数量一般等于数字的个数开根号。比如: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;
}
}