Skip to content

Commit c1e418a

Browse files
Merge pull request wangzheng0822#97 from Liam0205/15_bsearch
[cpp][15_bsearch] 实现带搜索策略的二分查找
2 parents b60926b + 3cd851d commit c1e418a

File tree

3 files changed

+104
-0
lines changed

3 files changed

+104
-0
lines changed

c-cpp/15_bsearch/.gitkeep

Whitespace-only changes.

c-cpp/15_bsearch/bsearch.hpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Created by Liam Huang (Liam0205) on 2018/10/24.
3+
*/
4+
5+
#ifndef BSEARCH_BSEARCH_HPP_
6+
#define BSEARCH_BSEARCH_HPP_
7+
8+
#include <iterator>
9+
#include <functional>
10+
11+
enum class BsearchPolicy { FIRST, LAST, UNSPECIFIED };
12+
13+
// Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement,
14+
// but with a bad time complexity. For better performance, iterators should meet
15+
// the RandomAccessIterator requirement.
16+
template <typename IterT,
17+
typename ValueT = typename std::iterator_traits<IterT>::value_type,
18+
typename Compare>
19+
IterT bsearch(IterT first,
20+
IterT last,
21+
ValueT target,
22+
Compare comp,
23+
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
24+
IterT result = last;
25+
while (std::distance(first, last) > 0) {
26+
IterT mid = first + std::distance(first, last) / 2;
27+
if (comp(*mid, target)) {
28+
first = mid + 1;
29+
} else if (comp(target, *mid)) {
30+
last = mid;
31+
} else { // equal
32+
if (policy == BsearchPolicy::FIRST) {
33+
if (mid == first or comp(*(mid - 1), *mid)) {
34+
result = mid;
35+
break;
36+
} else {
37+
last = mid;
38+
}
39+
} else if (policy == BsearchPolicy::LAST) {
40+
if (std::distance(mid, last) == 1 or comp(*mid, *(mid + 1))) {
41+
result = mid;
42+
break;
43+
} else {
44+
first = mid + 1;
45+
}
46+
} else {
47+
result = mid;
48+
break;
49+
}
50+
}
51+
}
52+
return result;
53+
}
54+
55+
template <typename IterT,
56+
typename ValueT = typename std::iterator_traits<IterT>::value_type,
57+
typename Compare = std::less<ValueT>>
58+
IterT bsearch(IterT first,
59+
IterT last,
60+
ValueT target,
61+
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
62+
return bsearch(first, last, target, Compare(), policy);
63+
}
64+
65+
#endif // BSEARCH_BSEARCH_HPP_
66+

c-cpp/15_bsearch/bsearch_test.cc

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Created by Liam Huang (Liam0205) on 2018/10/24.
3+
*/
4+
5+
#include <iostream>
6+
#include <vector>
7+
8+
#include "bsearch.hpp"
9+
10+
template <typename VecT, typename T = typename VecT::value_type>
11+
void test_bsearch(const VecT& test,
12+
T target,
13+
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
14+
auto it = bsearch(test.begin(), test.end(), target, policy);
15+
std::cout << std::distance(test.begin(), it) << std::endl;
16+
}
17+
18+
int main() {
19+
std::vector<int> test{0, 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 6, 7}; // std::less<int>()
20+
21+
test_bsearch(test, 8); // 14
22+
test_bsearch(test, -1); // 14
23+
test_bsearch(test, 0); // 0, 1
24+
test_bsearch(test, 0, BsearchPolicy::FIRST); // 0
25+
test_bsearch(test, 0, BsearchPolicy::LAST); // 1
26+
test_bsearch(test, 4); // 5, 6
27+
test_bsearch(test, 4, BsearchPolicy::FIRST); // 5
28+
test_bsearch(test, 4, BsearchPolicy::LAST); // 6
29+
test_bsearch(test, 5); // 7, 8, 9, 10, 11
30+
test_bsearch(test, 5, BsearchPolicy::FIRST); // 7
31+
test_bsearch(test, 5, BsearchPolicy::LAST); // 11
32+
test_bsearch(test, 7); // 13
33+
test_bsearch(test, 7, BsearchPolicy::FIRST); // 13
34+
test_bsearch(test, 7, BsearchPolicy::LAST); // 13
35+
36+
return 0;
37+
}
38+

0 commit comments

Comments
 (0)