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 <iterator>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
enum class BsearchPolicy { FIRST, LAST, UNSPECIFIED };
|
|
||||||
|
|
||||||
// Liam Huang: The algorithm works right with iterators that meet the ForwardIterator requirement,
|
// 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
|
// but with a bad time complexity. For better performance, iterators should meet
|
||||||
// the RandomAccessIterator requirement.
|
// the RandomAccessIterator requirement.
|
||||||
template <typename IterT,
|
template <typename IterT,
|
||||||
typename ValueT = typename std::iterator_traits<IterT>::value_type,
|
typename ValueT = typename std::iterator_traits<IterT>::value_type,
|
||||||
typename Compare>
|
typename Compare = std::less<ValueT>>
|
||||||
IterT bsearch(IterT first,
|
IterT bsearch(IterT first,
|
||||||
IterT last,
|
IterT last,
|
||||||
ValueT target,
|
ValueT target,
|
||||||
Compare comp,
|
Compare comp = Compare()) {
|
||||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
|
||||||
IterT result = last;
|
IterT result = last;
|
||||||
while (std::distance(first, last) > 0) {
|
while (std::distance(first, last) > 0) {
|
||||||
IterT mid = first + std::distance(first, last) / 2;
|
IterT mid = first + std::distance(first, last) / 2;
|
||||||
@ -29,38 +26,12 @@ IterT bsearch(IterT first,
|
|||||||
} else if (comp(target, *mid)) {
|
} else if (comp(target, *mid)) {
|
||||||
last = mid;
|
last = mid;
|
||||||
} else { // equal
|
} else { // equal
|
||||||
if (policy == BsearchPolicy::FIRST) {
|
|
||||||
if (mid == first or comp(*(mid - 1), *mid)) {
|
|
||||||
result = mid;
|
result = mid;
|
||||||
break;
|
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;
|
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_
|
#endif // BSEARCH_BSEARCH_HPP_
|
||||||
|
|
||||||
|
@ -8,10 +8,8 @@
|
|||||||
#include "bsearch.hpp"
|
#include "bsearch.hpp"
|
||||||
|
|
||||||
template <typename VecT, typename T = typename VecT::value_type>
|
template <typename VecT, typename T = typename VecT::value_type>
|
||||||
void test_bsearch(const VecT& test,
|
void test_bsearch(const VecT& test, T target) {
|
||||||
T target,
|
auto it = bsearch(test.begin(), test.end(), target);
|
||||||
BsearchPolicy policy = BsearchPolicy::UNSPECIFIED) {
|
|
||||||
auto it = bsearch(test.begin(), test.end(), target, policy);
|
|
||||||
std::cout << std::distance(test.begin(), it) << std::endl;
|
std::cout << std::distance(test.begin(), it) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,17 +19,9 @@ int main() {
|
|||||||
test_bsearch(test, 8); // 14
|
test_bsearch(test, 8); // 14
|
||||||
test_bsearch(test, -1); // 14
|
test_bsearch(test, -1); // 14
|
||||||
test_bsearch(test, 0); // 0, 1
|
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); // 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); // 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); // 13
|
||||||
test_bsearch(test, 7, BsearchPolicy::FIRST); // 13
|
|
||||||
test_bsearch(test, 7, BsearchPolicy::LAST); // 13
|
|
||||||
|
|
||||||
return 0;
|
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