二分查找
一般而言,对于包含n个元素的列表,用二分查找最多需要log2n步,而简单查找最多需要n步。
其实如果有m个元素
找出一个数n
使得m除以2的n次方小于等于1
那么需要判断的次数就是n+1
算法实现一
得数组长度length
判断num与数组的length/2的大小
如果大于length/2
判断length/2 + length/4 大小
。。。
如果小于length/2
判断length/2 - length/4 大小
。。。
太麻烦,而且不可行,如果需要比较n次,那么就得有2^(n-1)个if else 语句 【二叉树的形态】
算法实现二
使用递归,使用两个位置指针low,high,low代表最低索引,high代表最高索引
每次要测试的数test只是跟low和high 的中间值比较
如果大于中间值
low就变大,变为这个中间值
如果小于中间值
High就变小,变为这个中间值
每次只要根据变化后的low和high 计算出中间值,在跟test比较即可
而且每次都是相同的过程,可以使用递归,再次调用这个函数本身,
(其实这个函数的作用主要是获得下一个要与test比较的中间值并与其比较)
///**********************************************
///*************二分查找算法(2)
///使用递归的方式
///需要输入的参数有 数组,要判断的数值,一开始计算出的数组中间位置的下标,数组起始位置(一般为0),数组的长度
///每次变化的是与要测试数值比较的中间位置的下标num
///num根据与测试数值比较的情况进行改变,是变大还是变小
///返回:与test相等的数组元素的下标
///作用:判断一个数是否存在于数组中
///递归次数: 不多于n+1次(n为使用二分查找时比较的次数)
///**********************************************
int binary(int b[],int test,int num,int low,int high)
{
t_num++;
if(test>b[num])
{
low = num;
num = (low+high)/2;
if(num==high-1) ///防止测试数字不在数组中而无限递归,防止大于最大
{
return -1;
}
binary(b,test,num,low,high);
}
else if(test<b[num])
{
high = num;
num = (low+high)/2;
if(low == high) ///防止测试数字不在数组中而无限递归,防止小于最小
{
return -1;
}
binary(b,test,num,low,high);
}
else if(test == b[num])
{
return num;
}
}
算法实现3
使用循环,不用递归,依旧可以实现要测试 的数据只与中间值比较,只不过是使用循环不断刷新中间值
///**********************************************
///*************二分查找算法(3)
int binary_p(int e[],int length,int item)
{
int low = 0;
int mid;
int high = length-1;
while(low<=high)
{
p_num++;
mid = (low+high)/2;
if(item == e[mid])
{
return mid;
}
if(item > e[mid])
{
low = mid+1;
}
else
{
high = mid-1;
}
}
return -2;
}
两种算法比较:
如果要查找的数是第一个,算法2比算法3多比较一次
如果要查找的数是最后一个,算法3要多查找一次
如果要查找的数位于中间,两个算法查找的次数是相同的
对于数组或者链表这样的线性结构,如果涉及到其中元素的位置,可以设置几个位置指针用来在这个线性结构上来回查看,可以实现双向的查找,效率更高,也可以做更多事情,更灵活。
完整代码
#include <iostream>
using namespace std;
int t_num =0;///测试算法2的比较次数
int p_num =0;///测试算法3的比较次数
///**********************************************
///*************二分查找算法(2)
///使用递归的方式
///需要输入的参数有 数组,要判断的数值,一开始计算出的数组中间位置的下标,数组起始位置(一般为0),数组的长度
///每次变化的是与要测试数值比较的中间位置的下标num
///num根据与测试数值比较的情况进行改变,是变大还是变小
///返回:与test相等的数组元素的下标
///作用:判断一个数是否存在于数组中
///递归次数: 不多于n+1次(n为使用二分查找时比较的次数)
///**********************************************
int binary(int b[],int test,int num,int low,int high)
{
t_num++;
if(test>b[num])
{
low = num;
num = (low+high)/2;
if(num==high-1) ///防止测试数字不在数组中而无限递归,防止大于最大
{
return -1;
}
binary(b,test,num,low,high);
}
else if(test<b[num])
{
high = num;
num = (low+high)/2;
if(low == high) ///防止测试数字不在数组中而无限递归,防止小于最小
{
return -1;
}
binary(b,test,num,low,high);
}
else if(test == b[num])
{
return num;
}
}
///**********************************************
///*************二分查找算法(3)
int binary_p(int e[],int length,int item)
{
int low = 0;
int mid;
int high = length-1;
while(low<=high)
{
p_num++;
mid = (low+high)/2;
if(item == e[mid])
{
return mid;
}
if(item > e[mid])
{
low = mid+1;
}
else
{
high = mid-1;
}
}
return -2;
}
void test_02(int tu)///用来测试算法3
{
int c[90];
int kk;
for(int i =0;i<90;i++)
{
kk=i+5;
c[i]=kk;
}
for(int j=0;j<90;j++)
{
cout<<c[j]<<" ";
}
int length = sizeof(c)/sizeof(c[0]);
int ll = binary_p(c,length,tu);
if(ll!=-2)
{
cout<<ll<<endl;
}
else{
cout<<"nnnnnnn"<<endl;
}
cout<<p_num<<"p_num************"<<endl;
}
int main()
{
int tt;
cin>>tt;
int a[128];
int kk;
for(int i =0;i<128;i++)
{
kk=i+5;
a[i]=kk;
}
for(int j=0;j<128;j++)
{
cout<<a[j]<<" ";
}
cout<<endl;
int low1 =0;
int high1 = sizeof(a)/sizeof(a[0]);
int num1 = (low1+high1)/2;
int number = binary(a,tt,num1,low1,high1);
if(number !=-1)
{
cout<<number<<endl;
}
else
{
cout<<"no this number"<<endl;
}
cout<<"hello c++";
cout<<endl;
cout<<t_num<<"t_num**********"<<endl;
test_02(tt);
return 0;
}