首页 > 其他分享 >二分查找

二分查找

时间:2023-02-13 21:24:55浏览次数:38  
标签:二分 arr right int mid 查找 key left

二分查找

思路:

  • 找到最后一个小于等于IP的元素
  • 找到第一个大于等于IP的元素

前提条件:

  • 数据有序
  • 随机访问

实现:

  • 递归实现
  • 非递归(循环实现)

注意事项:

  1. 循环退出条件
  2. mid 的取值(重点防止越界)
  3. left 和 right的更新
#include<stdio.h>

#define SIZE(a) (sizeof(a) / sizeof(a[0]))

int bsearchByrecursion(int arr[], int n, int key);
int bsearchByloop(int arr[], int n, int key);
int searchFirstkey(int arr[], int n, int key);
int searchLastkey(int arr[], int n, int key);
int bsearchEqualorgreated(int arr[], int n, int key);
int bsearchEqualorless(int arr[], int n, int key);

int main(void)
{
	int arr[] = { 0,2,2,2,2,2,20,30,31,32,34,40,100 };
	int key = -50;
	int index = bsearchEqualorless(arr, SIZE(arr), 22);
	printf("index = %d\n", index);

	return 0;
}

// 递归实现二分查找
int bsearch(int arr[], int left, int right, int key)
{
	// 边界条件:区间为 0 
	if (left > right)
	{
		return -1;
	}
	// 递归公式
	/*
	   存在溢出风险。
	   原因:eft可能不断增大,如果到极限状态,
	   也就是left达到了right-1的地步的时候刚好数组的长度又很大,
	   那么就可能导致left + right的溢出出现负数
	   int mid = (left + right) / 2;
	*/
	// int mid = left + (right - left) / 2;			// 正确写法
	int mid = left + (right - left >> 1);
	if (key < arr[mid])
	{
		return bsearch(arr, left, mid - 1, key);
	}
	if (key > arr[mid])
	{
		return bsearch(arr, mid + 1, right, key);
	}
	return mid;			// key == arr[mid];
}

int bsearchByrecursion(int arr[], int n, int key)
{
	// 委托
	return bsearch(arr, 0, n - 1, key);
}

// 循环实现二分查找
int bsearchByloop(int arr[], int n, int key)
{
	int left = 0;
	int right = n - 1;

	// left = right说明还有一个元素,该元素还要和key进行比较
	while (left <= right)
	{
		int mid = left + (right - left >> 1);
		// 不能写成left = mid, right = mid;有可能出现死循环。
		if (key > arr[mid])
		{
			left = mid + 1;
		}
		else if (key < arr[mid])
		{
			right = mid - 1;
		}
		else
		{
			return mid;
		}
	}

	return -1;
}

// 寻找第一个与 key 相等的元素
int searchFirstkey(int arr[], int n, int key)
{
	int left = 0, right = n - 1, mid;
	while (left <= right)
	{
		mid = left + (right - left >> 1);
		if (key > arr[mid])
		{
			left = mid + 1;
		}
		else if (key < arr[mid])
		{
			right = mid - 1;
		}
		else
		{
			if (mid == 0 || arr[mid - 1] < key)		// 短路原则,不可能越界
			{
				return mid;
			}
			// 如果不是第一个与 key 相等的
			right = mid - 1;
		}
	}

	return -1;
}

// 查找最后一个与 key 相等的元素
int searchLastkey(int arr[], int n, int key)
{
	int left = 0, right = n - 1, mid;
	while (left <= right)
	{
		mid = left + (right - left >> 1);
		if (key > arr[mid])
		{
			left = mid + 1;
		}
		else if (key < arr[mid])
		{
			right = mid - 1;
		}
		else
		{
			if ((mid == n - 1) || (arr[mid + 1] > key))
			{
				return mid;
			}
			// 不是最后一个值等于 key 的元素
			left = mid + 1;
		}
	}

	return -1;		// 数组中不存在该元素
}

// 查找第一个大于等于 key 的元素
int bsearchEqualorgreated(int arr[], int n, int key)
{
	int left = 0, right = n - 1, mid;
	while (left <= right)
	{
		mid = left + (right - left >> 1);
		if (key > arr[mid])
		{
			left = mid + 1;
		}
		else
		{
			// 找到一个大于等于 key 的元素
			if (mid == left || arr[mid - 1] < key)
			{
				return mid;
			}
			// 如果不是第一个大于等于 key 的,则继续在左边找
			right = mid - 1;
		}
	}
        return -1;
}

// 查找最后一个小于等于 key 的元素
int bsearchEqualorless(int arr[], int n, int key)
{
	int left = 0, right = n - 1, mid;
	while (left <= right)
	{
		mid = left + (right - left >> 1);
		if (key < arr[mid])
		{
			right = mid - 1;
		}
		else
		{
			if (mid == right || arr[mid + 1] > key)
			{
				return mid;
			}
			left = mid + 1;
		}
	}

        return-1
}


标签:二分,arr,right,int,mid,查找,key,left
From: https://www.cnblogs.com/MyXjil/p/17117760.html

相关文章

  • 数组的排序和查找
    1.数组156注意数组知识点double[]hens={3,5,1,3.4,2,50};1.double[]表示是double类型的数组,数组名hens2.{3,5,1,3.4,2,50}表示数组的值/元素,依次表示数......
  • 二叉排序树的平均查找长度(成功&&不成功)
    二叉排序树的平均查找长度上图所示为二叉排序树查找成功时的平均查找长度:ASL=∑(本层高度*本层元素结点个数)/结点总数=(1*1+2*2+3*2)=11/5查找失败时的平......
  • 6-10 二分查找 (20分)
    本题要求实现二分查找算法。函数接口定义:PositionBinarySearch(ListL,ElementTypeX);其中List结构定义如下:typedefintPosition;typedefstructLNode*......
  • 数据库题(二)——查找每位玩家第一次登陆平台的日期
    题目写一条SQL 查询语句获取每位玩家第一次登陆平台的日期。查询结果的格式如下所示:Activity表:+-----------+-----------+------------+--------------+|player_......
  • C语言学习:查找字符与子串
     1#include<io_utils.h>2#include<string.h>34intmain(){5char*string="HelloWorld!";6char*result=strchr(string,'l');7char......
  • perl语言实现:查找file中相同的词,并输出
    #!/usr/bin/perlopen(FILE,"<ARGV[0]")ordie"Can'topen$ARGV[0]file";open(SAME_OUT,">same_out.h")prdie"Can'topensame_out.hfile";my$i=0;my$count=......
  • element-ui tree数据中根据id查找node
    递归返回正确数据尽早返回findNode(list,id){letresult=nullfor(leti=0;i<list.length;i++){if(list[i].ID===id){......
  • SQL SERVER——TempDB问题查找定位与解决
    SQLSERVER——TempDB问题查找定位与解决z_cloud_for_SQL2023-01-1229步骤1.TempDB压力诊断等待类型诊断TempDB的争用压力在等待篇中已经简单介绍,等待的表现......
  • 第二章_排序和查找
    1排序1.1排序#include<cstdio>#include<algorithm>usingnamespacestd;constintMAXN=100;intarr[MAXN];intmain(){intn;while(scanf("%d",......
  • 二分算法的实践总结.
    #include<bits/stdc++.h>usingnamespacestd;//整数二分算法模板——模板题AcWing789.数的范围boolcheck(intx){/*...*/}//检查x是否满足某种性质/......