二分查找算法的两种实现和缺陷
今天小编给大家分享的是二分查找算法的两种实现和缺陷的详细介绍,相信大部分人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,话不多说,一起往下看吧。
在学习算法的过程中,我们除了要了解某个算法的基本原理、实现方式,更重要的一个环节是分析算法的复杂度。在时间复杂度和空间复杂度之间,我们又会更注重时间复杂度,往往用牺牲空间换时间的方法提高时间效率。
时间复杂度按优劣排差不多集中在:
O(1), O(log n), O(n), O(n log n), O(n2), O(nk), O(2n)
二分查找法主要是解决在"一堆数中找出指定的数"这类问题,而想要应用二分查找法,这"一堆数"必须有一下特征:
存储在数组中
有序排列
所以如果是用链表存储的,就无法在其上应用二分查找法了。
至于是顺序递增排列还是递减排列,数组中是否存在相同的元素都不要紧。不过一般情况,我们还是希望并假设数组是递增排列,数组中的元素互不相同。
二分查找程序实现:
#include
using namespace std;
//while循环实现
int Binary_Search2(int array[], int n, int value)
{
int left = 0;
int right = n-1;
while (left <= right)//注意这里是"<="还是"=",若为"=",则循环里改为right = middle
{
int middle = left + ((right - left) >> 2);//直接平均可能會溢位,所以用此算法
if (array[middle] > value)
{
right = middle - 1;
}
else if(array[middle] < value)
{
left = middle + 1;
}
else
{
return middle;
}
}
return -1;
}
//递归实现
int Binary_Search3(int array[], int left,int right, int value)
{
if (left > right)//二分查找要有序
{
return -1;
}
int middle = left + ((right - left) >> 2);//直接平均可能會溢位,所以用此算法
if (array[middle] > value)
{
return Binary_Search3(array, left, middle - 1, value);
}
else if (array[middle] < value)
{
return Binary_Search3(array, middle + 1, right, value);
}
else
{
return middle;
}
}
int main()
{
int array[10] = { 1,2,3,5,7,8,9,11,13,45 };
int n = 0, num = 0,ret=0;
n = sizeof(array);
/*int left = 0, right = n-1;*/
cin >> num;
ret = Binary_Search2(array, n, num);
/*ret = Binary_Search3(array, left,right, num);*/
if (ret == -1)
{
cout << "查找失败!"<< endl;
}
else
{
cout << num << "是第" << ret + 1 << "个数" << endl;
}
system("pause");
return 0;
}
运行结果1:
8
8是第6个数
请按任意键继续. . .
运行结果2:
17
查找失败!
请按任意键继续. . .
二分查找法的缺陷
二分查找法的O(log n)让它成为十分高效的算法。不过它的缺陷却也是那么明显的。就在它的限定之上:
必须有序,我们很难保证我们的数组都是有序的。当然可以在构建数组的时候进行排序,可是又落到了第二个瓶颈上:它必须是数组。数组读取效率是O(1),可是它的插入和删除某个元素的效率却是O(n)。因而导致构建有序数组变成低效的事情。
解决这些缺陷问题更好的方法应该是使用二叉查找树了,最好自然是自平衡二叉查找树了,高效的(O(n logn))构建有序元素集合,又能如同二分查找法一样快速(O(log n))的搜寻目标数。
关于二分查找算法的两种实现和缺陷就分享到这里了,解决问题并不止文章中和大家分析的办法,不过本文分析的方法准确性是不容置疑的。如果喜欢本篇文章,不妨把它分享出去让更多的人看到。