#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;
}
}
}