//二分查找及其擴展實現
#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;
}
二分法及其拓展
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.