/**************************************************************************************/
//非递归的折半查找
static int BinarySearch1(int[] arr, int target) {
int left = 0;
int right = arr.length - 1; // 注意
while (left <= right) {
// 和 (left + right)/2 的结果相同,但是有效防止了 left 和 right 太大直接相加导致mid溢出。
int mid = left + (right - left) / 2;
if (arr[mid] > target)
right = mid - 1; // 注意
else if (arr[mid] < target)
left = mid + 1; // 注意
else
return mid;
}
return -1;
}
/**************************************************************************************/
/**************************************************************************************/
//递归的折半查找
static int BinarySearch2(int[] arr, int target, int left, int right) {
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] > target)
return BinarySearch2(arr, target, left, mid - 1);
else if (arr[mid] < target)
return BinarySearch2(arr, target, mid + 1, right);
else
return mid;
}
return -1;
}
/**************************************************************************************/
折半查找的改进:插值查找
考虑一个新问题,为什么上述算法一定要是折半,而不是折四分之一或者折更多呢?
打个比方,比如要在取值范围1 ~ 1000 之间 1000个元素从小到大均匀分布的数组中查找5, 我们自然会考虑从数组下标较小的开始查找,而不必从中间的500开始。即自适应确定查找位置。
二分查找中查找点计算如下:
int mid=(left+right)/2, 即 mid=left+1/2*(right-left)/2;
通过类比,我们可以将查找的点改进为如下:
int mid = left + (target - arr[left]) / (arr[right] - arr[left]) * (right - left);
二分(模糊)查找+插入
#include <iostream>
using namespace std;
int search(int* nums, int numsSize, int target) {
int left=0;int right=numsSize-1;
while(left<=right)
{
int mid=left+(right-left)/2;
if(target==nums[mid]) return mid;
else if(target<nums[mid])
{
right=mid-1;
}
else
{
left=mid+1;
}
}
return left;
}
int main()
{
//原数组为a的前5个数,a的总长度为6
//想插入的值:a[5]
int a[]={1,2,4,5,9,3};
cout<<"插入前的数组:";
for(int i=0;i<6;i++)
cout<<a[i]<<" ";
cout<<endl<<endl;
int loca=search(a,6,a[5]);
cout<<"应改将a[5]插入到下标为"<<loca<<"的地方"<<endl<<endl;
cout<<"插入后的数组:";
//插入过程
int temp=a[5];
for(int s=5;s>loca;s--)
{
a[s]=a[s-1];
}
a[loca]=temp;
for(int i=0;i<6;i++)
cout<<a[i]<<" ";
return 0;
}