分块查询算法(JAVA)

描述:

分块查找要求索引表是有序的,对块内节点没有排序要求,因此适合于节点动态变化的情况。

分块查找要求把一个大的线性表分解成若干块,每块中的节点可以任意存放,但块与块之间必须排序

步骤:

step1 先选取各块中的最大关键字构成一个索引表;

step2 查找分两个部分:先对索引表进行二分查找或顺序查找,以确定待查记录在哪一块中;

step3 然后,在已确定的块中用顺序法进行查找。

索引表的长度最佳为数据总长度开根号;

package cn.ljonah.search;

import java.util.ArrayList;

/**
 * @Descript:分块查找
 *
 * @author LJonah 2018年3月12日
 */
public class BlockSearch {
	
   private int[] index;//建立索引
   private ArrayList[] list;
	
	
	/**
	 * @Descript:初始化索引
	 *
	 * @author LJonah 2018年3月12日
	 * @param index
	 */
	public BlockSearch(int[] index){
		if(null != index && index.length!=0){
			this.index = index;
			this.list = new ArrayList[index.length];
			for (int i = 0;i < list.length;i++) {
				list[i] = new ArrayList();//初始化容器
			}
		}else{
			throw new Error("index cannot be null or empty");
		}
	}
	
	
	/**
	 * @Descript:插入索引
	 *
	 * @author LJonah 2018年3月12日
	 * @param value
	 */
	public void insert(int value){
		int i = binarySearch(value);
	    list[i].add(value);
	}
	
	
	/**
	 * @Descript:二分法查找
	 *
	 * @author LJonah 2018年3月12日
	 * @param value
	 * @return
	 */
	private int binarySearch(int value){
		int start = 0,end =index.length;int mid = -1;
		while(start<=end){
			mid=(start+end)/2;
			if(index[mid]>value){
				end = mid -1;
			}else{
	            //如果相等,也插入后面
				start = mid+1;
			}
		}
		return start;
	}
	
    /**
     * @Descript:查找元素
     *
     * @author LJonah 2018年3月12日
     * @param data
     * @return
     */
    public boolean search(int data)  
    {  
        int i=binarySearch(data);  
        for(int j=0;j<list[i].size();j++)  
        {  
            if(data==(int)list[i].get(j))  
            {  
                 System.out.println(String.format("查找元素为第: %d块  第%d个 元素",  i+1,j+1));  
                return true;  
            }  
        }  
        return false;  
    }  
    
	/**
	 * @Descript:打印每块的元素
	 *
	 * @author LJonah 2018年3月12日
	 */
	public void printAll(){
		for (int i = 0; i < list.length; i++) {
			ArrayList l = list[i];
			System.out.println("ArrayList["+i+"]:");
			
			for (int j = 0; j < l.size(); j++) {
				System.out.println(l.get(j)+"    ");
			}
		}
	}
	
	/**
	 * @Descript:测试
	 *
	 * @author LJonah 2018年3月12日
	 * @param args
	 */
	public static void main(String[] args) {
		 int []index={10,20,30};  
	        BlockSearch blocksearch=new BlockSearch(index);  
	        blocksearch.insert(1);  
	        blocksearch.insert(11);  
	        blocksearch.insert(21);  
	          
	        blocksearch.insert(2);  
	        blocksearch.insert(12);  
	        blocksearch.insert(22);  
	          
	        blocksearch.insert(5);  
	        blocksearch.insert(15);  
	        blocksearch.insert(25);  
	          
	        blocksearch.printAll();  
	          
	          System.out.println("查找值15   结果"+blocksearch.search(15));  
	        System.out.println("查找值29   结果"+blocksearch.search(29));  
	}

}

测试结果:

ArrayList[0]:
1    
2    
5    
ArrayList[1]:
11    
12    
15    
ArrayList[2]:
21    
22    
25    
查找元素为第: 2块  第3个 元素
查找值15   结果true
查找值29   结果false








### Java分块查找算法的实现与应用 #### 分块查找简介 分块查找法(Blocking Search),也被称为索引顺序查找法,适用于那些既不适合采用顺序查找也不适合折半查找的情况。该方法不仅需要原始的数据表,还需构建一个额外的“索引表”。这个索引表由若干个子集组成,每个子集中含有指向对应数据块的最大关键字以及该块的第一个元素的位置信息。值得注意的是,尽管各数据块内部可以保持无序状态,但是不同数据块之间的排列必须遵循升序原则[^3]。 #### 数据准备阶段 为了便于理解并展示如何利用Java编程语言来完成一次完整的分块查找操作,下面给出一段简单的代码片段用于创建测试环境: ```java import java.util.ArrayList; import java.util.List; public class BlockSearchExample { private static final int BLOCK_SIZE = 5; // 块大小设定为5 public static void main(String[] args){ List<Integer> dataList = new ArrayList<>(); // 初始化随机整数列表作为模拟数据库 for (int i=0;i<20;i++){ dataList.add((int)(Math.random()*100)); } System.out.println("Original Data:"); System.out.println(dataList); // 对整个list进行排序以便后续处理 dataList.sort(Integer::compareTo); // 构建索引表... } } ``` 这段代码初始化了一个包含20个随机整数值的`dataList`,并通过调用内置函数对其进行排序。这一步骤是为了简化之后的操作流程——因为即使在真实的应用场景里,我们也会希望输入的数据至少能在逻辑上满足一定的有序性条件。 #### 创建索引表 接下来的部分展示了怎样基于上述已有的有序序列建立起相应的索引结构: ```java // ...继续上面的例子... List<BlockIndex> indexTable = buildIndexTable(dataList, BLOCK_SIZE); System.out.println("\nIndex Table:"); for(BlockIndex bi : indexTable){ System.out.printf("(%d,%d)\n",bi.maxValue(),bi.startPos()); } Integer target = 78; // 设定要查询的目标值 boolean found = blockSearch(indexTable,dataList,target); if(found){ System.out.printf("%d was found.\n",target); }else{ System.out.printf("%d not found\n",target); } } /** * 根据给定的数据列表和指定的块尺寸构造索引表。 */ private static List<BlockIndex> buildIndexTable(List<Integer> data,int blockSize){ List<BlockIndex> result = new ArrayList<>(); for(int i=0,j=data.size();i<j;i+=blockSize){ int end = Math.min(i+blockSize-1,j-1); result.add(new BlockIndex(data.get(end),i)); } return result; } /** * 定义BlockIndex类表示单个索引条目。 */ record BlockIndex(int maxValue, int startPos){} /** * 使用分块查找的方式定位目标值。 */ private static boolean blockSearch(List<BlockIndex> indices,List<Integer> data,Integer key){ for(var idx:indices){ if(key<=idx.maxValue()){ // 如果key小于等于当前最大值,则只在这部分范围内做线性扫描即可 for(int k=idx.startPos();k<data.size()&&k<(idx.startPos()+BLOCK_SIZE);++k){ if(data.get(k).equals(key)){ return true; } } break; } } return false; } } ``` 这里定义了两个辅助性的私有静态成员函数:一个是用来生成所需的索引表格;另一个则是执行具体的分块查找过程。当尝试寻找某特定键值时,会先遍历索引表直到发现第一个大于或等于目标值的最大值为止,随后仅需对该区间内的项目逐一检验便能得出结论。 #### 应用场景分析 分块查找特别适合应用于如下几种情况: - 需要在大型文件或其他持久化对象中快速检索少量记录的情形; - 或者面对频繁更新但每次变动量较小的数据集合时,相比于完全重建一棵平衡树而言,维护一张动态调整的小规模索引表可能更加高效合理一些。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值