数据结构查找算法之二分查找
二分查找
二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。
- 前提: 线性表中的记录必须是关键字有序(通常从小到大),线性表必须采用顺序存储。
- 基本思想: 取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;否则,在右半区查找。不断重复,直到查找成功或查找失败为止。
- 复杂度
二分算法步骤描述
前提:有序数组中查找关键词所在的位置
-
首先确定整个查找区间的中间位置 mid = strat+(end-strat)/2
-
用待查关键字key值与中间位置的关键字值进行比较;
若相等,则查找成功
若key小于a[k],则在前(左)半个区域继续进行折半查找;
若key大于a[k],则在后(右)半个区域继续进行折半查找
-
对确定的缩小区域再按折半公式,重复上述步骤。
二分查找的应用场景:
二分查找目的是在一堆数中找到指定的数。
使用二分查找这些数据需要有的特征(面试容易问):
- 存储在数组中。
- 有序的排列。
如果是链表就无法使用二分查找。
顺序数组是递增递减,是否有重复的数据没有关系。
二分查找的实现(递归算+非递归)
递归算
折半查找,递归实现(模板)
/*折半查找,递归实现*/
template<class T>
int Binary_Search(T *x, int N, T keyword)
{
int low = 0, high = N-1,mid;
while(low <= high)
{
mid = (low + high)/2;
if(x[mid] == keyword)
return mid;
if(x[mid] < keyword)
low = mid + 1;
else
high = mid -1;
}
return -1;
}
折半查找,递归实现
/*折半查找,递归实现*/
int binarySearch(int *arr , int low , int high , int target)//递归实现
{
int middle = (low + high)/2;
if(low > high)
return -1;
if(arr[middle] == target)
return middle;
if(arr[middle] > target)
return binarySearch( arr , low , middle - 1 , target);
if(arr[middle] < target)
return binarySearch( arr , middle + 1 , high , target);
};
非递归实现
/**
* 二分查找普通实现。
* @param srcArray 有序数组
* @param key 查找元素
* @return 不存在返回-1,存在返回对应的数组下标
*/
int binarySearch1(int a[], int n , int target)//循环实现
{
int low = 0 ,high = n , middle;
middle = (low + high)/2;
if (key == a[middle]) {
return mid;
}
while(low < high)
{
middle = (low + high)/2;
if(target == a[middle])
return middle;
else if(target > a[middle])
low = middle +1;
else if(target < a[middle])
high = middle;
}
return -1;
};
参考例子
#include<iostream>
using namespace std;
int binarySearch(int *arr , int low , int high , int target)//递归实现
{
int middle = (low + high)/2;
if(low > high)
return -1;
if(arr[middle] == target)
return middle;
if(arr[middle] > target)
return binarySearch( arr , low , middle - 1 , target);
if(arr[middle] < target)
return binarySearch( arr , middle + 1 , high , target);
};
int binarySearch1(int a[], int n , int target)//循环实现
{
int low = 0 ,high = n , middle;
while(low < high)
{
middle = (low + high)/2;
if(target == a[middle])
return middle;
else if(target > a[middle])
low = middle +1;
else if(target < a[middle])
high = middle;
}
return -1;
};
int main()
{
int a[10] = {5,6,7,8,9, 10 , 11, 12 ,13, 14};
int index = binarySearch( a , 0 , 9 , 12);
cout<<index<< endl;
int index2 = binarySearch1(a,10,12);
cout<<index2<< endl;
system("pause");
}
后记:
查找和排序都是在程序设计中经常用到的算法,查找相对而言较为简单,不外乎顺序查找、二分查找、哈希表查找和二叉排序树查找。
在面试的时候,不管是用循环还是用递归,面试官都期待应聘者能够信手拈来写出完整的二分查找代码,否则可能连继续面试的兴趣都没有。
以上两句话引出自《剑指Offer:名企面试官精讲典型面试题》