查找:分块查找(java)

1.排序思想

1.将待排序的数组(n)进行分块.
2.例如分为s块.
那么每一块的结点个数为:n/s;
最后一块的结点个数:<=n/s;
3.对每i块有要求
第 i-1 块中结点的最大值<第 i 块中结点的最小值
第 i 块中结点的最大值<第 i+1 块中结点的最小值
4.先找待查找的num所在的快,然后再该块中顺序找对应的num.

2.排序流程图

在这里插入图片描述

3.打印排序结果

0:[0~5] maxNum=211:[6~11] maxNum=452:[12~17] maxNum=73
开始查找:52
num:52 可能在第 2 块中:[12~17]
52在数组中的索引位置: 15

4.算法实现

4.1数据结构

块Bean

public class Block {
	int maxNum;// 块中的最大值
	int startIndex;// 块在数组中的起始索引位置
	int endIndex;// 块在数组中的结束索引位置

	public Block(int startIndex, int endIndex, int maxNum) {
		this.startIndex = startIndex;
		this.endIndex = endIndex;
		this.maxNum = maxNum;
	}
	
	@Override
	public String toString() {
		StringBuilder sBuilder=new StringBuilder();
		sBuilder.append("[").append(startIndex).append("~").append(endIndex).append("]");
		sBuilder.append(" maxNum=").append(maxNum);
		return sBuilder.toString();
	}
}

4.2获取所在块

/**
	 * 查找num所在的块,比较的是Block中的maxNum
	 * 
	 * @param blocks
	 * @param num
	 * @return -1表示未找到所在块
	 */
	private static int getBlockIndex(Block[] blocks, int num) {
		// 1.使用二分查找 找到num所在块的位置
		int low = 0;
		int high = blocks.length - 1;
		int mid = 0;
		while (low <= high) {
			mid = (low + high) / 2;
			// 2.表示找到的值等于当前块的最大值,那么直接返回当前索引即可
			if (num == blocks[mid].maxNum) {
				return mid;
			} else if (num > blocks[mid].maxNum) {
				low = mid + 1;
			} else if (num < blocks[mid].maxNum) {
				high = mid - 1;
			}
		}
		// 3.走到这里表示num与块中最大值一样的值,那么num就在 块的索引= (low+high)/2 中
		int resultIndex = (low + high + 1) / 2;
		if (resultIndex >= blocks.length) {
			resultIndex = -1;// 表示未找到
		}
		return resultIndex;
	}

4.3分块查找

/**
	 * 
	 * @param blocks 块的索引表:块中的可以无序的,但是块与块之间是有序的
	 *               例如:blocks[0]中的最大值小于blocks[1]中的最小值,依次类推
	 * @param array  待查询的数组
	 * @param num    待查找的值
	 * @return num 在array数组中的索引位置:-1表示未找到
	 */
	public static int blocksSearch(Block[] blocks, int array[], int num) {
		// 1.先从块的索引表中找出当前值所在的块
		int blockIndex = getBlockIndex(blocks, num);// 快的索引
		// -1表示块未找到,那么对应num的在array肯定找不到
		if (blockIndex == -1) {
			return -1;
		}
		System.out.println("num:" + num + " 可能在第 " + blockIndex + " 块中:[" + blocks[blockIndex].startIndex + "~"
				+ blocks[blockIndex].endIndex + "]");
		// 2.在块中使用顺序查找.
		int blockStart = blocks[blockIndex].startIndex;
		for (int start = blocks[blockIndex].startIndex, end = blocks[blockIndex].endIndex; start <= end; start++, end--) {
			if (num == array[start]) {
				return start;
			}
			if (num == array[end]) {
				return end;
			}
		}
		return -1;
	}

5.调用示例

public class BlockSearchTest {

	public static void main(String[] args) {
		// 1. 待查找数组
		int array[] = new int[] { 16, 5, 9, 12, 21, 18, 32, 23, 37, 26, 45, 34, 50, 48, 61, 52, 73, 66 };
		// 2.将数组进行分块
		// 第0块:0-5:[16, 5, 9, 12, 21, 18] maxNum=21
		// 第1块:6-11:[32, 23, 37, 26, 45, 34] maxNum=45
		// 第2块:12-17:[50, 48, 61, 52, 73, 66 ] maxNum=73
		Block b0 = new Block(0, 5, 21);
		Block b1 = new Block(6, 11, 45);
		Block b2 = new Block(12, 17, 73);
		Block blocks[] = new Block[] { b0, b1, b2 };
		System.out.println("第0块:" + b0.toString());
		System.out.println("第1块:" + b1.toString());
		System.out.println("第2块:" + b2.toString());
		// 3.查找的值
		int num = 52;
		System.out.println("开始查找:" + num);
		int index = BlockSearch.blocksSearch(blocks, array, num);
		System.out.println(num + "在数组中的索引位置: " + index);

	}

}

6.复杂度

时间复杂度:O( n \sqrt{n} n )
空间复杂度:O(1)

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值