复习梗概
- 二分搜索法的end有两种定义方式,两种分别是什么含义?
- 二分搜索法end的两种定义方式分别影响了什么?(结束条件,更新指针)
- 二分搜索法的结束条件和更新指针两步代码?
- 二分搜索法的整体流程?
- 二分搜索法图解
- !!!我们不必纠结于二分搜索法mid =(begin+end)/2这个过程,middle是不是真的中间那一位,还是中间两位中的一个(偶数总数),因为是有序数组,严格比较大小缩小搜寻范围即可,mid差一两位没所谓根本
- 二分搜索法可以用于优化插入排序
二分搜索法是什么,时间复杂度
二分搜索法 : 用于寻找有序数组中的某个元素的位置 ,平均时间复杂度O(logn)(每次砍一半),没有稳定性
二分搜索法整体流程
- 初始化begin和end指针,初始化mid指针
- 若mid大于num,更新begin指针,mid小于num更新end指针(假设是递增序列)
- 若找到mid=num,退出并返回mid
- 若begin与end相遇或错过(视end定义而变),退出并返回没找到
- 循环上述
二分搜素法代码(end是数组末元素索引)
//!二分搜索法可以有两种写法,主要区别体现在end的定义,以及找不到元素结束搜索的条件(begin与end的位置关系)上
//! 比如下面这个,end的定义是被搜索那一块数组最后元素的索引
void binarySearch(vector<int> &array, int element)
{
int begin = 0;//begin代表的是,查找数组中的第一个元素的索引,初始为0
int end = array.size()-1;//end此时代表的是查找数组的最后一位元素索引
while (begin <= end)//当begin与end错过时,查找数组中不再有任何元素,搜索结束
{
int middle = (begin + end) / 2;
if (array[middle] == element)
{
cout << "Search Success Index = " << middle << endl;
return;
}
else if (element < array[middle])
{
end = middle -1;//更新end指针,指向新的搜索数组的末尾元素(不包括middle,所以要-1)
}
else if (element > array[middle])
{
begin = middle + 1;//更新begin指针,指向新的搜索数组的首元素(不包括middle,所以要+1)
}
}
cout<<"Element Not Find"<<endl;
return;
}
输入数组:
1 4 6 8 11 15 29 31
二分搜索基础版
搜索 19
Element Not Find
算法用时:(微秒)
[AlgoTime: 2000 us]
搜索完成
二分搜索法代码(end是数组末元素索引+1)
//! 下面这个,end的定义是被搜索那一块数组最后元素的索引+1
void binarySearch(vector<int> &array, int element)
{
int begin = 0;//begin代表的是,查找数组中的第一个元素的索引,初始为0
int end = array.size();
//!这里需要注意,二分搜索法里的end不是数组最后的索引啦,是查找数组的最后一位的索引+1,初始值等于数组长度,是为了什么?
while (begin < end)//当begin与end相等时,查找数组中不再有任何元素,搜索结束,画个图就明白了
{
int middle = (begin + end) / 2;
if (array[middle] == element)
{
cout << "Search Success Index = " << middle << endl;
return;
}
else if (element < array[middle])
{
end = middle;//更新end指针,指向新的搜索数组的末尾元素的后一位(就是middle,所以不用-1)
}
else if (element > array[middle])
{
begin = middle + 1;
}
}
cout<<"Element Not Find"<<endl;
return;
}
输入数组:
1 4 6 8 11 15 29 31
二分搜索基础版
搜索 29
Search Success Index = 6
算法用时:(微秒)
[AlgoTime: 4000 us]
搜索完成
完整代码
#include <iostream>
#include <vector>
#include "MeasureAlgoTime.hpp"
using namespace std;
//二分搜索法 : 用于寻找有序数组中的某个元素的位置 ,平均时间复杂度O(logn)(每次砍一半),没有稳定性
void vectorPrint(vector<int> &array)
{
for (int i = 0; i < array.size(); i++)
{
cout << array[i] << ' ';
}
cout << endl;
}
//!二分搜索法可以有两种写法,主要区别体现在end的定义,以及找不到元素结束搜索的条件(begin与end的位置关系)上
//! 比如下面这个,end的定义是被搜索那一块数组最后元素的索引
void binarySearch(vector<int> &array, int element)
{
int begin = 0;//begin代表的是,查找数组中的第一个元素的索引,初始为0
int end = array.size()-1;//end此时代表的是查找数组的最后一位元素索引
while (begin <= end)//当begin与end错过时,查找数组中不再有任何元素,搜索结束
{
int middle = (begin + end) / 2;
if (array[middle] == element)
{
cout << "Search Success Index = " << middle << endl;
return;
}
else if (element < array[middle])
{
end = middle -1;//更新end指针,指向新的搜索数组的末尾元素(不包括middle,所以要-1)
}
else if (element > array[middle])
{
begin = middle + 1;//更新begin指针,指向新的搜索数组的首元素(不包括middle,所以要+1)
}
}
cout<<"Element Not Find"<<endl;
return;
}
//! 下面这个,end的定义是被搜索那一块数组最后元素的索引+1
void binarySearch1thRE(vector<int> &array, int element)
{
int begin = 0;//begin代表的是,查找数组中的第一个元素的索引,初始为0
int end = array.size();
//!这里需要注意,二分搜索法里的end不是数组最后的索引啦,是查找数组的最后一位的索引+1,初始值等于数组长度,是为了什么?
while (begin < end)//当begin与end相等时,查找数组中不再有任何元素,搜索结束,画个图就明白了
{
int middle = (begin + end) / 2;
if (array[middle] == element)
{
cout << "Search Success Index = " << middle << endl;
return;
}
else if (element < array[middle])
{
end = middle;//更新end指针,指向新的搜索数组的末尾元素的后一位(就是middle,所以不用-1)
}
else if (element > array[middle])
{
begin = middle + 1;
}
}
cout<<"Element Not Find"<<endl;
return;
}
int main()
{
Tools::Time::AlgoTimeUs time1;
Tools::Time::AlgoTimeUs time2;
Tools::Time::AlgoTimeUs time3;
vector<int> array;
array = {1,4,6,8,11,15,29,31};
vector<int> array2 = array;
vector<int> array3 = array;
cout << "输入数组:" << endl;
time1.start();
vectorPrint(array);
cout << "二分搜索基础版" << endl;
binarySearch(array,19);
cout << "算法用时:(微秒)";
time1.printElapsed();
cout << "搜索完成"<< endl;
cout << "输入数组:" << endl;
time2.start();
vectorPrint(array2);
cout << "二分搜索基础版" << endl;
binarySearch1thRE(array2,29);
cout << "算法用时:(微秒)";
time1.printElapsed();
cout << "搜索完成"<< endl;
return 0;
}