查找算法-01二分查找

二分查找

文章目录

  • 二分查找
    • 1. 算法说明
    • 2. 算法原理
    • 3. 动图演示
    • 4. 代码实现
    • 5. 算法变形
      • 5.1 查找目标在集合中第一次出现的位置
      • 5.2 图解
      • 5.3 查找目标在集合中最后一次出现的位置

1. 算法说明

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

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

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

2. 算法原理

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

3. 动图演示

查找算法-01二分查找_第1张图片

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 图解

查找算法-01二分查找_第2张图片

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("在集合中未找到目标元素");
	}
}

你可能感兴趣的:(算法及数据结构,二分,动图,二分查找详解)