二分查找

 

二分查找的核心思想是在有序的序列中,每次与中间元素比较,若比中间元素大,则查找元素出现在右半部分,反之则出现在左半部分,然后对改新的区间进行如上操作。直到找到对应元素,或者low > high 递归终止条件。时间复杂度为O(logn)

局限性

  • 需要有序数据,对动态数据集不怎么使用,性能耗费高。适用于插入、删除操作少的场合
  • 数据量太小不适合。数据量过小时,和线性查找耗时差不多。
  • 数据量太大也不适合。二分查找依赖数组,因此需要连续内存,数据量太大,例如1GB的数据,将需要连续1GB的内存,这比较困难。

a. 最简单的情况:有序递增数组中,不存在重复元素

//二分查找有序非重复数组,返回下标,无则返回-1
int binary_search(int data[], int size, int search_data)
{
	int low = 0, high = size - 1;
	int mid = 0;

	//采用while循环进行二分查找
	while (low <= high)
	{
		mid = low + ((high - low) >> 1);
		//若data[mid] == search_data,则直接返回下标
		if (data[mid] == search_data)
		{
			return mid;
		}
		//若data[mid] < search_data,则查找数据处于mid右边
		else if (data[mid] < search_data)
		{
			low = mid + 1;
		}
		//若data[mid] > search_data,则查找数据处于mid左边
		else
		{
			high = mid - 1;
		}
	}

	return -1;
}

b. 有序递增数组,查找第一个值等于给定值的元素。

可以在a代码中对查找相等进行区分,判断是否为首次出现。

//二分查找有序有重复数组,返回查找元素第一次出现的下标,无则返回-1
int binary_search_first_data(int data[], int size, int search_data)
{
	int low = 0, high = size - 1;
	int mid = 0;

	//采用while循环进行二分查找
	while (low <= high)
	{
		mid = low + ((high - low) >> 1);
		//若data[mid] == search_data,则要判断mid是否为首个元素下标
		if (data[mid] == search_data)
		{
			//若mid为0,或mid的前一个不为search_data,则为首个元素下标
			if (mid == 0 || data[mid - 1] != search_data)
			{
				return mid;
			}
			else
			{
				high = mid - 1;
			}
		}
		//若data[mid] < search_data,则查找数据处于mid右边
		else if (data[mid] < search_data)
		{
			low = mid + 1;
		}
		//若data[mid] > search_data,则查找数据处于mid左边
		else
		{
			high = mid - 1;
		}
	}

	return -1;
}

c. 有序递增数组,查找最后一个值等于给定值的元素。

可以在c代码中对查找相等进行区分,判断是否为末次出现。

//二分查找有序有重复数组,返回查找元素最后一次出现的下标,无则返回-1
int binary_search_last_data(int data[], int size, int search_data)
{
	int low = 0, high = size - 1;
	int mid = 0;

	//采用while循环进行二分查找
	while (low <= high)
	{
		mid = low + ((high - low) >> 1);
		//若data[mid] == search_data,则要判断mid是否为最后一个元素下标
		if (data[mid] == search_data)
		{
			//若mid为0,或mid的后一个不为search_data,则为最后一个元素下标
			if (mid == (size - 1) || data[mid + 1] != search_data)
			{
				return mid;
			}
			else
			{
				low = mid + 1;
			}
		}
		//若data[mid] < search_data,则查找数据处于mid右边
		else if (data[mid] < search_data)
		{
			low = mid + 1;
		}
		//若data[mid] > search_data,则查找数据处于mid左边
		else
		{
			high = mid - 1;
		}
	}

	return -1;
}

d. 有序递增数组,查找第一个大于等于给定值的元素。

//二分查找有序有重复数组,查找第一个大于等于给定值的元素,无则返回-1
int binary_search_first_exceed(int data[], int size, int search_data)
{
	int low = 0, high = size - 1;
	int mid = 0;

	//采用while循环进行二分查找
	while (low <= high)
	{
		mid = low + ((high - low) >> 1);

		//若data[mid] < search_data,则查找数据处于mid右边
		if (data[mid] < search_data)
		{
			low = mid + 1;
		}
		//若data[mid] >= search_data,则对mid的前一位进行判断
		else
		{
			if (mid == 0 || data[mid - 1] < search_data)
			{
				return mid;
			}
			else
			{
				high = mid - 1;
			}
		}
	}

	return -1;
}

e. 有序递增数组,查找最后一个小于等于给定值的元素。

//二分查找有序有重复数组,查找最后一个小于等于给定值的元素,无则返回-1
int binary_search_last_below(int data[], int size, int search_data)
{
	int low = 0, high = size - 1;
	int mid = 0;

	//采用while循环进行二分查找
	while (low <= high)
	{
		mid = low + ((high - low) >> 1);

		//若data[mid] > search_data,则查找数据处于mid左边
		if (data[mid] > search_data)
		{
			high = mid - 1;
		}
		//若data[mid] >= search_data,则对mid的后一位进行判断
		else
		{
			if (mid == size - 1 || data[mid + 1] > search_data)
			{
				return mid;
			}
			else
			{
				low = mid + 1;
			}
		}
	}

	return -1;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值