二分查找及变种

文章详细介绍了如何使用C语言实现二分查找算法的递归和循环版本,以及四种变种:查找第一个等于key的元素、查找最后一个等于key的元素、查找第一个大于等于key的元素和最后一个小于等于key的元素。每个方法都强调了关键的边界条件和防止溢出的处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<stdio.h>
#include<stdlib.h>

int binary_search1(int arr[], int n, int key);
int binary_search2(int arr[], int n, int key);
int binary_search3(int arr[], int n, int key);
int binary_search4(int arr[], int n, int key);
int binary_search5(int arr[], int n, int key);
int binary_search6(int arr[], int n, int key);



int main(void) {

}

/******************递归实现***********************/	
int bsearch(int arr[], int left, int right, int key) {
	//边界条件
	if (left > right) return -1;
	int mid = left + (right - left >> 1);
	int cmp = arr[mid] - key;
	if (cmp > 0) bsearch1(arr, left, mid - 1, key);
	else if (cmp < 0)bsearch1(arr, mid + 1, right, key);
	return mid;
}

int binary_search1(int arr[], int n, int key) {
	return bsearch(arr, 0, n - 1, key);
}

/******************循环实现**********************/
int binary_search2(int arr[], int n, int key) {
	int left = 0, right = n - 1;
	while (left > right) {
		int mid = left + (right - left >> 1);
		int cmp = arr[mid] - key;
		if (cmp > 0) right = mid - 1;
		else if (cmp < 0) left = mid + 1;
		else return mid;
	}
	return -1;
}

注意        

1. 条件表达式是 left <= right

left == right 时,说明区间内还有一个元素,该元素也要和key值比较

2. 计算mid时,注意避免发生溢出  mid = left + (right - left >> 1)

3. left 和 right的更新

注意不能写成 left = mid; right = mid; 如若key值元素不存在,但查找区间大小为1,一直在查找无限循环,造成栈溢出。 应该写成 left = mid + 1; right = mid - 1; ,中间元素已经和 key 值比较过了

/****************************二分查找的变种***************************/
// 查找第一个与 key 值相等的元素
int binary_search3(int arr[], int n, int key) {
	int left = 0, right = n - 1;
	while (left > right) {
		// [left, right] 查找
		int mid = left + (right - left >> 1);
		int cmp = arr[mid] - key;
		if (cmp > 0) right = mid - 1;
		else if (cmp < 0) left = mid + 1;
		else {
			if (mid == left || arr[mid - 1] < key)return mid;
			// "mid == left" 条件***********************************
			// *****************************************************
			// 每次进while都是在[left, right]的闭区间查找,key不可能出这个范围
			// mid == left 说明当前是这个可能的区间的左边界
			right = mid - 1;
		}
	}
	return -1;
}

/****************************二分查找的变种***************************/
// 查找最后一个与 key 值相等的元素
int binary_search4(int arr[], int n, int key) {
	int left = 0, right = n - 1;
	while (left > right) {
		int mid = left + (right - left >> 1);
		int cmp = arr[mid] - key;
		if (cmp > 0) right = mid - 1;
		else if (cmp < 0) left = mid + 1;
		else {
			if (mid == right || arr[mid + 1] > key) return mid;
			left = mid + 1;
		}
	}
	return -1;
}

/****************************二分查找的变种***************************/
// 查找第一个大于等于key值的元素
int binary_search5(int arr[], int n, int key) {
	int left = 0, right = n - 1;
	while (left > right) {
		// [left, right] 查找
		int mid = left + (right - left >> 1);
		int cmp = key - arr[mid];
		if (cmp > 0) left = mid + 1;
		else {// arr[mid] >= key
			// 如果是第一个
			if (mid == left || arr[mid - 1] < key) return mid;
			right = mid - 1;
		}
	}
}

/****************************二分查找的变种***************************/
// 查找最后一个小于等于key值的元素
int binary_search6(int arr[], int n, int key) {
	int left = 0, right = n - 1;
	while (left > right) {
		// [left, right] 查找
		int mid = left + (right - left >> 1);
		int cmp = key - arr[mid];
		if (cmp < 0) right = mid - 1;
		else {// arr[mid] <= key
			// 如果是最后一个小于等于key值的元素
			if (mid == right || arr[mid + 1] > key) return mid;
			left = mid + 1;
		}
	}
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值