查找算法-01二分查找

算法及数据结构 专栏收录该内容
8 篇文章 0 订阅

二分查找

1. 算法说明

摘自百度百科:二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

从上述说明文字,我们可以得到两个关键点

  • 采用顺序存储结构 -> 数据存储结构必须是有序的集合
  • 元素按关键字有序排列 -> 集合中的元素已经排序。

2. 算法原理

  1. 首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较。
  2. 如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表。
  3. 如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。
  4. 重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

3. 动图演示

image

4. 代码实现

@Test
public void binarySearch0() {
	int target = 2;
	int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7};

	int startIndex = 0, endIndex = arr.length - 1;
	while (startIndex <= endIndex) {

		//计算中间索引
		int midIndex = (startIndex + endIndex) >>> 1;
		int midValue = arr[midIndex];

		if (target == midValue) {
			log.info("查找目标:{} 所在集合索引位置:{}", target, midIndex);
			return;
		} else if (target > midValue) {
			//目标元素>中间值,将中间索引向后推,向后查找
			startIndex = midIndex + 1;
		} else {
			//target < midValue
			//目标元素<中间值,将中间索引向前推,向前查找
			endIndex = midIndex - 1;
		}
	}
	log.info("在集合中未找到目标,返回-1");
}

5. 算法变形

5.1 查找目标在集合中第一次出现的位置

@Test
public void binarySearch1() {
	int target = 2;
	int[] arr = new int[]{1, 2, 2, 3, 4};

	int startIndex = 0, endIndex = arr.length - 1;
	while (startIndex <= endIndex) {

		//计算中间索引
		int midIndex = (startIndex + endIndex) >>> 1;
		int midValue = arr[midIndex];

		log.info("startIndex:{}, endIndex:{}, midIndex:{}, midValue:{}", startIndex, endIndex, midIndex, midValue);

		if (target > midValue) {
			//目标元素>中间值,将中间索引向后推,向后查找
			startIndex = midIndex + 1;
		} else {
			//target <= midValue
			//目标元素<=中间值,将中间索引向前推,向前查找。 【标记】
			endIndex = midIndex - 1;
		}

	}

	/*
	startIndex < arr.length 防止当arr为空时,索引越界
	当【标记】时,假设这时候,索引为2(midIndex),前一位索引1的元素与目标不一致。则后续循环时endIndex=2(midIndex-1)
	一直不变,startIndex会向endIndex靠拢,退出循环时,startIndex会比endIndex大1
	*/
	if (startIndex < arr.length && arr[startIndex] == target) {
		log.info("位置:{}", startIndex);
	} else {
		log.info("在集合中未找到目标元素");
	}
}

5.2 图解

image

5.3 查找目标在集合中最后一次出现的位置

@Test
public void binarySearch2() {
	int target = 2;
	int[] arr = new int[]{1, 2, 2, 3, 4};

	int startIndex = 0, endIndex = arr.length - 1;
	while (startIndex <= endIndex) {
		int midIndex = (startIndex + endIndex) >>> 1;
		int midValue = arr[midIndex];
		if (target >= midValue) {
			startIndex = midIndex + 1;
		} else {
			endIndex = midIndex - 1;
		}
	}

	if (endIndex < arr.length && arr[endIndex] == target) {
		log.info("位置:{}", endIndex);
	} else {
		log.info("在集合中未找到目标元素");
	}
}
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论
请先登录 后发表评论~
©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏作者

Eleven...

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值