Merge pull request #111 from Liam0205/16_bsearch
[cpp][16_bsearch] all varients' impl.
This commit is contained in:
commit
bdce324f77
@ -8,19 +8,16 @@
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
|
||||
enum class BsearchPolicy { FIRST, LAST, UNSPECIFIED };
|
||||
|
||||
// Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement,
|
||||
// but with a bad time complexity. For better performance, iterators should meet
|
||||
// the RandomAccessIterator requirement.
|
||||
template <typename IterT,
|
||||
typename ValueT = typename std::iterator_traits<IterT>::value_type,
|
||||
typename Compare>
|
||||
typename Compare = std::less<ValueT>>
|
||||
IterT bsearch(IterT first,
|
||||
IterT last,
|
||||
ValueT target,
|
||||
Compare comp,
|
||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
||||
Compare comp = Compare()) {
|
||||
IterT result = last;
|
||||
while (std::distance(first, last) > 0) {
|
||||
IterT mid = first + std::distance(first, last) / 2;
|
||||
@ -29,38 +26,12 @@ IterT bsearch(IterT first,
|
||||
} else if (comp(target, *mid)) {
|
||||
last = mid;
|
||||
} else { // equal
|
||||
if (policy == BsearchPolicy::FIRST) {
|
||||
if (mid == first or comp(*(mid - 1), *mid)) {
|
||||
result = mid;
|
||||
break;
|
||||
} else {
|
||||
last = mid;
|
||||
}
|
||||
} else if (policy == BsearchPolicy::LAST) {
|
||||
if (std::distance(mid, last) == 1 or comp(*mid, *(mid + 1))) {
|
||||
result = mid;
|
||||
break;
|
||||
} else {
|
||||
first = mid + 1;
|
||||
}
|
||||
} else {
|
||||
result = mid;
|
||||
break;
|
||||
}
|
||||
result = mid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename IterT,
|
||||
typename ValueT = typename std::iterator_traits<IterT>::value_type,
|
||||
typename Compare = std::less<ValueT>>
|
||||
IterT bsearch(IterT first,
|
||||
IterT last,
|
||||
ValueT target,
|
||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
||||
return bsearch(first, last, target, Compare(), policy);
|
||||
}
|
||||
|
||||
#endif // BSEARCH_BSEARCH_HPP_
|
||||
|
||||
|
@ -8,10 +8,8 @@
|
||||
#include "bsearch.hpp"
|
||||
|
||||
template <typename VecT, typename T = typename VecT::value_type>
|
||||
void test_bsearch(const VecT& test,
|
||||
T target,
|
||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
||||
auto it = bsearch(test.begin(), test.end(), target, policy);
|
||||
void test_bsearch(const VecT& test, T target) {
|
||||
auto it = bsearch(test.begin(), test.end(), target);
|
||||
std::cout << std::distance(test.begin(), it) << std::endl;
|
||||
}
|
||||
|
||||
@ -21,17 +19,9 @@ int main() {
|
||||
test_bsearch(test, 8); // 14
|
||||
test_bsearch(test, -1); // 14
|
||||
test_bsearch(test, 0); // 0, 1
|
||||
test_bsearch(test, 0, BsearchPolicy::FIRST); // 0
|
||||
test_bsearch(test, 0, BsearchPolicy::LAST); // 1
|
||||
test_bsearch(test, 4); // 5, 6
|
||||
test_bsearch(test, 4, BsearchPolicy::FIRST); // 5
|
||||
test_bsearch(test, 4, BsearchPolicy::LAST); // 6
|
||||
test_bsearch(test, 5); // 7, 8, 9, 10, 11
|
||||
test_bsearch(test, 5, BsearchPolicy::FIRST); // 7
|
||||
test_bsearch(test, 5, BsearchPolicy::LAST); // 11
|
||||
test_bsearch(test, 7); // 13
|
||||
test_bsearch(test, 7, BsearchPolicy::FIRST); // 13
|
||||
test_bsearch(test, 7, BsearchPolicy::LAST); // 13
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
0
c-cpp/16_bsearch/.gitkeep
Normal file
0
c-cpp/16_bsearch/.gitkeep
Normal file
90
c-cpp/16_bsearch/bsearch_varients.hpp
Normal file
90
c-cpp/16_bsearch/bsearch_varients.hpp
Normal file
@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Created by Liam Huang (Liam0205) on 2018/10/26.
|
||||
*/
|
||||
|
||||
#ifndef BSEARCH_BSEARCH_VARIENTS_HPP_
|
||||
#define BSEARCH_BSEARCH_VARIENTS_HPP_
|
||||
|
||||
#include <iterator>
|
||||
#include <functional>
|
||||
|
||||
enum class BsearchPolicy { UNSPECIFIED, FIRST, LAST, FIRST_NOT_LESS, LAST_NOT_GREATER };
|
||||
|
||||
// Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement,
|
||||
// but with a bad time complexity. For better performance, iterators should meet
|
||||
// the RandomAccessIterator requirement.
|
||||
template <typename IterT,
|
||||
typename ValueT = typename std::iterator_traits<IterT>::value_type,
|
||||
typename Compare>
|
||||
IterT bsearch(IterT first,
|
||||
IterT last,
|
||||
ValueT target,
|
||||
Compare comp,
|
||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
||||
IterT result = last;
|
||||
while (std::distance(first, last) > 0) {
|
||||
IterT mid = first + std::distance(first, last) / 2;
|
||||
if (policy == BsearchPolicy::FIRST_NOT_LESS) {
|
||||
if (!comp(*mid, target)) {
|
||||
if (mid == first or comp(*(mid - 1), target)) {
|
||||
result = mid;
|
||||
break;
|
||||
} else {
|
||||
last = mid;
|
||||
}
|
||||
} else {
|
||||
first = mid + 1;
|
||||
}
|
||||
} else if (policy == BsearchPolicy::LAST_NOT_GREATER) {
|
||||
if (comp(target, *mid)) {
|
||||
last = mid;
|
||||
} else {
|
||||
if (std::distance(mid, last) == 1 or comp(target, *(mid + 1))) {
|
||||
result = mid;
|
||||
break;
|
||||
} else {
|
||||
first = mid + 1;
|
||||
}
|
||||
}
|
||||
} else { // policy == UNSPECIFIED or FIRST or LAST
|
||||
if (comp(*mid, target)) {
|
||||
first = mid + 1;
|
||||
} else if (comp(target, *mid)) {
|
||||
last = mid;
|
||||
} else { // equal
|
||||
if (policy == BsearchPolicy::FIRST) {
|
||||
if (mid == first or comp(*(mid - 1), *mid)) {
|
||||
result = mid;
|
||||
break;
|
||||
} else {
|
||||
last = mid;
|
||||
}
|
||||
} else if (policy == BsearchPolicy::LAST) {
|
||||
if (std::distance(mid, last) == 1 or comp(*mid, *(mid + 1))) {
|
||||
result = mid;
|
||||
break;
|
||||
} else {
|
||||
first = mid + 1;
|
||||
}
|
||||
} else {
|
||||
result = mid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename IterT,
|
||||
typename ValueT = typename std::iterator_traits<IterT>::value_type,
|
||||
typename Compare = std::less<ValueT>>
|
||||
IterT bsearch(IterT first,
|
||||
IterT last,
|
||||
ValueT target,
|
||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
||||
return bsearch(first, last, target, Compare(), policy);
|
||||
}
|
||||
|
||||
#endif // BSEARCH_BSEARCH_VARIENTS_HPP_
|
||||
|
41
c-cpp/16_bsearch/bsearch_varients_test.cc
Normal file
41
c-cpp/16_bsearch/bsearch_varients_test.cc
Normal file
@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Created by Liam Huang (Liam0205) on 2018/10/26.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "bsearch_varients.hpp"
|
||||
|
||||
template <typename VecT, typename T = typename VecT::value_type>
|
||||
void test_bsearch(const VecT& test,
|
||||
T target,
|
||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
||||
auto it = bsearch(test.begin(), test.end(), target, policy);
|
||||
std::cout << std::distance(test.begin(), it) << std::endl;
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::vector<int> test{0, 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 5, 6, 8}; // std::less<int>()
|
||||
|
||||
test_bsearch(test, 8); // 14
|
||||
test_bsearch(test, -1); // 14
|
||||
test_bsearch(test, 0); // 0, 1
|
||||
test_bsearch(test, 0, BsearchPolicy::FIRST); // 0
|
||||
test_bsearch(test, 0, BsearchPolicy::LAST); // 1
|
||||
test_bsearch(test, 4); // 5, 6
|
||||
test_bsearch(test, 4, BsearchPolicy::FIRST); // 5
|
||||
test_bsearch(test, 4, BsearchPolicy::LAST); // 6
|
||||
test_bsearch(test, 5); // 7, 8, 9, 10, 11
|
||||
test_bsearch(test, 5, BsearchPolicy::FIRST); // 7
|
||||
test_bsearch(test, 5, BsearchPolicy::LAST); // 11
|
||||
test_bsearch(test, 7, BsearchPolicy::FIRST_NOT_LESS); // 13
|
||||
test_bsearch(test, 7, BsearchPolicy::LAST_NOT_GREATER); // 12
|
||||
test_bsearch(test, 7, BsearchPolicy::FIRST); // 14
|
||||
test_bsearch(test, 8); // 13
|
||||
test_bsearch(test, 8, BsearchPolicy::FIRST); // 13
|
||||
test_bsearch(test, 8, BsearchPolicy::LAST); // 13
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user