折半查找:又叫二分查找,采用分治思想,适用于不经常变动且查找频繁的表;
算法思想:
将n个元素(假设n个元素升序)分为大致相同的两部分,取data[n / 2] 与目标元素m比较:
若data[n/2] == m:return (n / 2);
若data[n/2] > m:则我们只要在data[]的左半部分继续查找;
若data[n/2] < m:则我们只要在data[]的有半部分继续查找;
时间复杂度:O(logn);
优点:比较次数少,查找速度快,平均性能好;
缺点:要求待查表为"有序表",且插入删除困难;
边界错误问题:
(1)左闭右开区间([left , right))。
left = 0 , right = length;
循环条件while(left < right):
data[middle] > m:right = middle;
data[middle] < m: left = middle + 1;
(2)左右皆闭区间([left , right])。
left = 0 , right = length - 1;
循环条件while(left <= right):
data[middle] > m:right = middle - 1;
data[middle] < m:left = middle + 1;
循环体外的初始化条件与循环体内的初始化条件,在迭代时必须一致的区间规则;
代码实现:
#include<iostream>
#include<exception>
using namespace std;
//---------------------------------------------二分查找(顺序查找)---------------------------------------
int BinSearch_Soulation1(const int* data , int length , int m)
{
//左闭右闭区间
int left = 0;
int right = length - 1 ;
while(left <= right)
{
//middle = (right + left) / 2 不可取;
//若(right + left) 溢出时,出现错误;
int middle = left + (right - left) / 2;
if(data[middle] > m)
{
right = middle - 1;
}
else if(data[middle] < m)
{
left = middle + 1;
}
else
{
return middle;
}
}
return -1;
}
int BinSearch_Soulation2(const int* data , int length , int m)
{
//左闭右开区间
int left = 0;
int right = length;
int middle;
while(left < right)
{
middle = left + ((right - left) / 2);
if(data[middle] > m)
{
right = middle;
}
else if(data[middle] < m)
{
left = middle + 1;
}
else
{
return middle;
}
}
return -1;
}
int BinSearch_Soulation3(const int* data, int length, int m)
{
int left, right, middle;
left = -1, right = length;
while (left + 1 != right)//这个循环维持的条件是left<right && array[left]<v<=array[right],所以到最后的时候,
{//如果可以找到目标,则只剩下两个数,并且满足 array[left]<v<=array[right],是要查找的数是right
middle = left + (right - left) / 2;
if (data[middle] < m)//必须保证array[left]<v<=array[right],所以left = middle;
{//如果left =middle+1,则有可能出现 array[left]<=v的情况
left = middle;
}
else
{
right = middle;
}
}
if (right >= length || data[right] != m)
{
right = -1;
}
return right;
}