//二分查找及其扩展实现
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
using namespace std;
// 二分寻找值为value的元素
int binary_search(vector<int> &array, int left, int right, int value) //left right不能小于0
{
if (array.empty())
{
return -1;
}
while (left <= right) // 写成 left < right 可能找不到value 如 {1 2 3 4 5} value = 5时 left==right才能找到value
{
int mid = left + ((right - left) >> 1); // 如果写成 middle= (left+right)>>1;
if (array[mid] < value) //这样的话left与right的值比较大的时候,其和可能溢出,减法可以使得结果为一个right还小的值
{ //移位运算和直接的除法运算,移位要更快一点
left = mid + 1; // 如果left = mid; 可能死循环 如上面 left指向4 right指向5 会死循环 而right不会因等于mid而死循环
}
else if (array[mid] > value)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
int binary_min_search(vector<int> &array, int left, int right, int value) // 寻找值为value的最小下标元素
{
if (array.empty())
{
return -1;
}
while (left < right) // left == right会无限循环
{
int mid = left + ((right - left) >> 1);
if (array[mid] < value)
{
left = mid + 1;
}
else if (array[mid] > value)
{
right = mid - 1;
}
else
{
right = mid; // right = mid - 1的话可能找不到
}
}
if (array[left] == value)
{
return left;
}
else
{
return -1;
}
}
int binary_max_search(vector<int> &arr, int left, int right, int value) // 寻找值为value的最大下标元素
{
if (arr.empty())
{
return -1;
}
while (left < right - 1) // left < right 的话可能陷入无限循环
{
int mid = left + ((right - left) >> 1);
if (arr[mid] < value)
{
left = mid + 1;
}
else if (arr[mid] == value)
{
left = mid;
}
else
{
right = mid - 1;
}
}
if (arr[right] == value)
{
return right;
}
else if (arr[left] == value)
{
return left;
}
else
{
return -1;
}
}
int binary_justsmall_search(vector<int> &arr, int left, int right, int value) // 寻找小于value的最大元素
{
if (arr.empty())
{
return -1;
}
while (left < right - 1)
{
int mid = left + ((right - left) >> 1);
if (arr[mid] < value)
{
left = mid;
}
else
{
right = mid - 1;
}
}
if (arr[right] < value)
{
return right;
}
else if (arr[left] < value)
{
return left;
}
else
{
return -1;
}
}
int binary_justgreater_search(vector<int> &arr, int left, int right, int value) // 寻找大于的value的最小元素
{
if (arr.empty())
{
return -1;
}
while (left < right)
{
int mid = left + ((right - left) >> 1);
if (arr[mid] <= value)
{
left = mid + 1;
}
else
{
right = mid;
}
}
if (arr[right] > value)
{
return right;
}
else
{
return -1;
}
}
int print(vector<int> &arr)
{
for (size_t i = 0; i < 10; ++i)
{
cout << arr[i] << " ";
}
cout << endl;
return 0;
}
int main()
{
static default_random_engine e;
static uniform_int_distribution<unsigned> u(1, 10);
vector<int> arr;
for (size_t i = 0; i < 10; ++i)
{
arr.push_back(u(e));
}
sort(arr.begin(), arr.end());
print(arr);
cout << binary_search(arr, 0, 9, 5) << endl;
cout << binary_min_search(arr, 0, 9, 5) << endl;
cout << binary_max_search(arr, 0, 9, 5) << endl;
cout << binary_justsmall_search(arr, 0, 9, 5) << endl;
cout << binary_justgreater_search(arr, 0, 9, 5) << endl;
return 0;
}
二分法及其拓展
最新推荐文章于 2022-06-23 01:23:33 发布