二分查找---折半查找

注意:查找的前提必须是有序数组或者容器

思想:

定义llow为顺序表最左端元素位置,high为顺序表右端元素位置。定义mid = (low+high) / 2,即顺序表的中间位置,然后用所查找的值与mid所在位置处的值比较,由于列表有序,若所查找的值比mid小,则只需在表的前半部分查找,否则只需在表的后半部分查找(若第一次比较就发现两值相等则直接返回当前值所在的位置),以此类推,直至查找到所寻找的值或确定所查找的值不在该列表内为止(即查找失败)。

有序数组中没有重复元素的情况下

#include<iostream>
using namespace std;
//二分查找算法---返回查找到的元素的下标
//数组 数组长度 查找的值
int test(int arr[],int len,int val)
{
    
    
	//判断传入的数组值是否合法
	if (len < 1)
	{
    
    
		return -1;
	}
	//最小值和最大值
	int low = 0;
	int high = len - 1;
	//
	while (low <= high)
	{
    
    
		int mid = (low + high) / 2;
		//判断查找元素值比中间元素值大还是小
		if (val > arr[mid])
		{
    
    
			low = mid + 1; //那么要去比mid大的左边区间进行折半查找,需要把最小值更新到mid+1
		}
		if (val < arr[mid])
		{
    
    
			high = mid - 1;//那么要去比mid小的右边区间进行折半查找,需要把最大值更新到mid-1
		}
		if (val == arr[mid])
		{
    
    
			return mid; //返回的就是查找到的元素下标
		}
	}

}
int main()
{
    
    
	int arr[8] = {
    
     -1,0,1,2,3,4,10,12};
	int num=test(arr,8,4);
	cout << "4元素在数组中下标位置为:" << num << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

如果一个数组里有多个连续重复的值,我们想找到连续重复值中下标最小的应该怎么办呢?我们只需对else语句略作修改

#include<iostream>
using namespace std;
//二分查找算法---返回查找到的元素的下标
//数组 数组长度 查找的值
int test(int arr[],int len,int val)
{
    
    
	//判断传入的数组值是否合法
	if (len < 1)
	{
    
    
		return -1;
	}
	//最小值和最大值
	int low = 0;
	int high = len - 1;
	//
	while (low <= high)
	{
    
    
		int mid = (low + high) / 2;
		//判断查找元素值比中间元素值大还是小
		if (val > arr[mid])
		{
    
    
			low = mid + 1; //那么要去比mid大的左边区间进行折半查找,需要把最小值更新到mid+1
		}
		if (val < arr[mid])
		{
    
    
			high = mid - 1;//那么要去比mid小的右边区间进行折半查找,需要把最大值更新到mid-1
		}
		if (val == arr[mid])
		{
    
    
		//mid值要大于最小值的下标,判断mid前面是否有与val值相等的元素
			while (mid > low && arr[mid - 1] == val)//在不越界的前提下后一个值与前一个值相等
			{
    
    
				--mid;//下标减一
			}
			return mid; //返回的就是查找到的元素下标
		}
	}

}
int main()
{
    
    
	int arr[9] = {
    
     -1,1,1,2,3,4,4,10,12};
	int num=test(arr,8,4);
	cout << "4元素在数组中下标位置为:" << num << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

递归方法实现

#include<iostream>
using namespace std;
//二分查找算法---返回查找到的元素的下标
//数组 数组长度 查找的值
int test(int arr[],int len,int val,int low,int high)
{
    
    
	//判断传入的数组值是否合法
	if (len < 1)
	{
    
    
		return -1;
	}
	//
	int mid = -1;
	//
	if (low <= high)
	{
    
    
		mid = (low + high) / 2;
		//判断查找元素值比中间元素值大还是小
		if (val > arr[mid])//要去mid右边,即比左边比mid大的区间
		{
    
    
			//这里如果在大区间里面找到了val的位置,就会返回下标,用mid来接收
			//没有找到返回-1
			mid=test(arr, len, val, mid + 1, high);
		}
		if (val < arr[mid])//要去mid左边,即比左边比mid小的区间
		{
    
    
			//这里如果在小区间里面找到了val的位置,就会返回下标,用mid来接收
			mid=test(arr, len, val, low, mid - 1);
		}
		if (val == arr[mid])
		{
    
    
			while (mid > low && arr[mid - 1] == val)//在不越界的前提下后一个值与前一个值相等
			{
    
    
				--mid;//下标减一
			}
			return mid; //返回的就是查找到的元素下标
		}
	}
	  //元素不在当前区间数组中
		return mid;
}
int main()
{
    
    
	int arr[9] = {
    
     -1,1,1,2,3,4,4,10,12};
	int num=test(arr,9,4,0,8);
	cout << "10元素在数组中下标位置为:" << num << endl;
	system("pause");
	return 0;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_53157173/article/details/114692948