您的位置:首页 > 其它

关于二分查找的写法

2016-11-23 17:09 246 查看
参考文章:https://www.zhihu.com/question/36132386

https://www.oschina.net/code/snippet_126720_6472

http://www.cnblogs.com/cchun/archive/2012/07/24/2605991.html

方法1:对于不下降序列a,n为序列a元素的个数,key为关键字:

(1)求最下的i,使得a[i]=key,若不存在,则返回-1

int binary_search_1(int a[], int n, int key)
{
int m, l = 0, r = n - 1;//闭区间[0, n - 1]
while (l < r)
{
m = l + ((r - l) >> 1);//向下取整
if (a[m] < key) l = m + 1;
else r = m;
}
if (a[r] == key) return r;
return -1;
}

作者:LightGHLi
链接:https://www.zhihu.com/question/36132386/answer/105595067
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
(2)求最大的i,使得a[i] = key,若不存在,则返回-1
int binary_search_2(int a[], int n, int key)
{
int m, l = 0, r = n - 1;//闭区间[0, n - 1]
while (l < r)
{
m = l + ((r + 1 - l) >> 1);//向上取整
if (a[m] <= key) l = m;
else r = m - 1;
}
if (a[l] == key) return l;
return -1;
}

作者:LightGHLi
链接:https://www.zhihu.com/question/36132386/answer/105595067
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

(3)求最小的i,使得a[i] > key,若不存在,则返回-1
int binary_search_3(int a[], int n, int key)
{
int m, l = 0, r = n - 1;//闭区间[0, n - 1]
while (l < r)
{
m = l + ((r - l) >> 1);//向下取整
if (a[m] <= key) l = m + 1;
else r = m;
}
if (a[r] > key) return r;
return -1;
}

作者:LightGHLi
链接:https://www.zhihu.com/question/36132386/answer/105595067
来源:知乎
著作权归作者所有,转载请联系作者获得授权。


(4)求最大的i,使得a[i] < key,若不存在,则返回-1
int binary_search_4(int a[], int n, int key)
{
int m, l = 0, r = n - 1;//闭区间[0, n - 1]
while (l < r)
{
m = l + ((r + 1 - l) >> 1);//向上取整
if (a[m] < key) l = m;
else r = m - 1;
}
if (a[l] < key) return l;
return -1;
}

作者:LightGHLi
链接:https://www.zhihu.com/question/36132386/answer/105595067
来源:知乎
著作权归作者所有,转载请联系作者获得授权。


更简洁的形式:
(1)
int ans = std::lower_bound(a, a + n, key) - a;
ans = (ans == n || a[ans] != key) ? -1 : ans;
(2)
int ans = std::upper_bound(a, a + n, key) - a;
ans = (ans == 0 || a[ans - 1] != key) ? -1 : ans - 1;
(3)
int ans = std::upper_bound(a, a + n, key) - a;
ans = (ans == n) ? -1 : ans;
(4)
int ans = std::lower_bound(a, a + n, key) - a;
ans = (ans == 0) ? -1 : ans - 1;


方法2:
(1)STL中的binary_search
判断值是否存在

 binary_search()
        bool binary_search(ForwardIterator first, ForwardIterator last, const LessThanComparable& value);
        bool binary_search(ForwardIterator first, ForwardIteratorlast, const T& value, StrictWeakOrdering comp);
        在[first,last)中查找value,如果找到返回Ture,否则返回False
        二分检索,复杂度O(log(last-first))

(2)lower_bound()与upper_bound()

ForwardIter lower_bound(ForwardIter first, ForwardIter last,const _Tp& val)算法返回一个非递减序列[first, last)中的第一个大于等于值val的位置。ForwardIter upper_bound(ForwardIter first,
ForwardIter last, const _Tp& val)算法返回一个非递减序列[first, last)中的第一个大于值val的位置。



(3)equal_range(),这个返回的是一个pair型,注意pair里面的两个区间端点都是迭代器。

如果想用int数组下标来进行运算,那么可以将迭代器转化为小标,这个跟指针转化为下标是一致的,就是当前迭代器减去数组头地址。其实lower_bound与upper_bound的返回值就是equal_range的两个区间端点,注意这个区间是左闭右开区间,即右边的端点是指定元素的下一个位置。如果找不到元素,那么lower_bound的迭代器等于upper_bound的迭代器,这是都是等于大于元素的第一个迭代器。

equal_range是C++ STL中的一种二分查找的算法,试图在已排序的[first,last)中寻找value,它返回一对迭代器i和j,其中i是在不破坏次序的前提下,
value可插入的第一个位置(亦即lower_bound),j则是在不破坏次序的前提下,value可插入的最后一个位置(亦即upper_bound),因此,[i,j)内的每个
元素都等同于value,而且[i,j)是[first,last)之中符合此一性质的最大子区间

    如果以稍许不同的角度来思考equal_range,我们可把它想成是[first,last)内"与value等同"之所有元素形成的区间A,由于[fist,last)有序(sorted),所以我们
知道"与value等同"之所有元素一定都相邻,于是,算法lower_bound返回区间A的第一个迭代器,算法upper_bound返回区间A的最后一个元素的下一个位置,
算法equal_range则是以pair的形式将两者都返回

   即使[fist,last)并未含有"与value等同"之任何元素,以上叙述仍然合理,这种情况下,"与value等同"之所有元素形成的,其实是一个空区间,在不破坏次序的情况下,
只有一个位置可以插入value,而equal_range所返回的pair,其第一和第二(都是迭代器)皆指向该位置。

(4)STL中的includes可以判断一个区间是否是另一个区间的子集。注意,这里说的是子集,比如1 3 5是1 2 3 4 5的一个子集。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

int main()
{
vector<int> coll;
vector<int> sub;

for(int i = 1; i <= 9; ++i)
{
coll.push_back(i);
}

sub.push_back(2);
sub.push_back(4);
sub.push_back(6);

cout << "coll : " << endl;
copy(coll.begin(), coll.end(), ostream_iterator<int>(cout, " "));
cout << endl;

cout << "sub : " << endl;
copy(sub.begin(), sub.end(), ostream_iterator<int>(cout, " "));
cout << endl;

if(includes(coll.begin(), coll.end(), sub.begin(), sub.end()))
{
cout << "sub is a sub set of coll" << endl;
}
else
{
cout << "not a sub set" << endl;
}

return 0;
}

以下为测试代码:
#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>

using namespace std;
int main()
{
vector<int> v;
vector<int>::iterator iter;
pair<vector<int>::iterator, vector<int>::iterator> vecpair;

for (int i = 1; i <= 20; i++) {
v.push_back(i % 6);
}
sort(v.begin(), v.end());
cout << "array: " << endl << " ";
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl << endl;

/* lower_bound */
cout << "lower_bound function, value = 3: " << endl;
iter = lower_bound(v.begin(), v.end(), 3);
cout << " [first, iter] = ";
copy(v.begin(), iter, ostream_iterator<int>(cout, " "));
cout << endl;
cout << " [iter, last] = ";
copy(iter, v.end(), ostream_iterator<int>(cout, " "));
cout << endl << endl;

/* upper_bound */
cout << "upper_bound function, value = 3: " << endl;
iter = upper_bound(v.begin(), v.end(), 3);
cout << " [first, iter] = ";
copy(v.begin(), iter, ostream_iterator<int>(cout, " "));
cout << endl;
cout << " [iter, last] = ";
copy(iter, v.end(), ostream_iterator<int>(cout, " "));
cout << endl << endl;

/* equal_range */
cout << "euqual_range function value = 3: " << endl;
vecpair = equal_range(v.begin(), v.end(), 3);

cout << " [vecpair->first, vecpair->second] = ";
copy(vecpair.first, vecpair.second, ostream_iterator<int>(cout, " "));
cout << endl << endl;

/* binary_search */
cout << "binary_search function value = 3: " << endl;
cout << "3 is " << (binary_search(v.begin(), v.end(), 3) ? "" : "not ") << " in array" << endl;
cout << endl;

/* binary_search */
cout << "binary_search function value = 6: " << endl;
cout << "6 is " << (binary_search(v.begin(), v.end(), 6) ? "" : "not ") << " in array" << endl;
cout << endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: