查找算法之二分查找(折半查找)

二分查找是一种基于有序数组的高效查找算法,其时间复杂度为O(logn),优于遍历数组的O(n)。通过不断缩小查找区间,它能在较短的步骤中找到目标元素。文章介绍了二分查找的过程,包括确定数组有序、设置起始和终止位置,以及关键的中间位置计算。在查找过程中,根据中间元素与目标值的比较来调整查找范围,直至找到目标或确定数组中不存在该元素。
摘要由CSDN通过智能技术生成

        今天,我们学习的是排序查找算法中,最容易理解并且掌握的二分查找。

        二分查找又名折半查找。折半查找的前提要求,即所查询的数组必须是一个有序数组。(无论升序降序)只有当所查询数据是规律排布的情况下,我们才可以进行查找。(后面会详细解释为什么必须是有序数组)

二分查找的优点

        倘若给定上述数组,你打算如何寻找元素5呢?

        我们先来看看遍历数组的查找过程。首先从数组首元素开始判断,1×、2×、2×、3×、4×、5√。我们可以看到比较次数为6次。

        而采用二分查找需要几次呢?标定mid = (left+right)/2,mid=3<5。此时left = mid+1,mid=5。mid = 5,我们找到了元素5,整个过程只需要两次。

        通过上述两个例子的对比,我们不难看出,遍历数组的时间复杂度O(n)相较于二分查找的时间复杂度O(logn),同样查找情况下,二分查找的速度远快于遍历。

二分查找的过程

        首先我们来看二分查找的查找方式。 在查找前,我们需要做三个准备工作。

        1、确定查找数组是否有序,以及数组的长度。

        2、标定起始位置和终止位置。

        3、在起始位置与中止位置之间,标定中间位置。(这一步是二分查找的关键)

         接下来我们推演二分查找的过程(假定我们查找元素5):

二分查找初始状态

从给定数组[1,2,2,3,4,5,6]可以得知,该有序数组长度为7,起始位置标定为0,终止位置标定为6,则中间位置mid标定为(0+6)/2=3。此时,我们已经做好了二分查找的前期准备工作。

int arr[] = { 1,2,2,3,4,5,6 };
	int num = 0;
	printf("请输入要查询的元素:");
	scanf("%d", &num);

	int arrSize = sizeof(arr) / sizeof(int);
    
	int left = 0;
	int right = arrSize-1;
    int mid = (left + right)/2;

接下来进入查找环节。

        我们已知mid下标里的元素是3。3<5,所以应当在mid-right的区间里去继续查找(这时候必须要求数组的有序性,因为无序数组无法判断左右两边的大小,所以数组有序性是二分查找的关键)

第一次查找过后

 此时,我们抛弃了整个数组大区间,因为我们知道mid是小于目标数字的,所以比mid小的区间内数字应该全部剔除,包括mid。我们就得到了第二次查找到起始状态

int mid = (right + left) / 2;

		if (arr[mid] < num)    //如果mid<所查询的数字,我们应当抛弃左边小于mid的空间
		{
			left = mid + 1;
		}
		else if (arr[mid] > num)    //如果mid>所查询的数字,我们应当抛弃右边大于mid的空间
		{
			right = mid - 1;
		}

新的left = mid + 1,right保持不变,新的mid继续保持mid = (left + right)/2 = 5。此时我们再对比mid和输入的数字可得,mid == 5。查找结束,我们已经找到了需要的数字。

        倘若我们希望查找7这个元素(可知当前数组内没有7这个元素)。这时,我们应当如何终止查找呢?

       我们可知,当循环到最后一次时,7是大于整个数组内所有元素的,这个时候left已经和right重合了。查询区间内,已经没有可以遍历的元素。于是结束循环后,left=7,而right依然等于6。此时我们只需要判断left是否大于right,就可以知道整个数组内没有符合条件的元素了,因为如果符合条件,在之前的循环就会跳出,从而使得left最多与right相等(数组的最后一个元素),不会出现left大于right的情况。

while (left <= right)
	{
		int mid = (right + left) / 2;

		if (arr[mid] < num)    //如果mid<所查询的数字,我们应当抛弃左边小于mid的空间
		{
			left = mid + 1;
		}
		else if (arr[mid] > num)    //如果mid>所查询的数字,我们应当抛弃右边大于mid的空间
		{
			right = mid - 1;
		}
		else
		{
			printf("找到了,元素下标为:%d\n", mid);
			break;
		}
	}

	if(left > right)    //此时已经遍历完整个数组,依然没有寻找到给定数字
	{
		printf("没找到此元素\n");
	}

小结

        我们可以知道,二分查找是一种非常优秀、并且基础的查找算法。它的原理通俗易懂,即不断地抛弃掉不符合条件的区间,缩小区间,简化查找步骤。但是它也是一种局限性非常强的查找算法——必须在有序空间内进行查找!倘若数据是无序存放的,又何谈mid左右区间的大小呢?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值