下面是使用迭代器的qsort实现,就像在std::sort中一样
// iterator check
template <typename It, typename T>
constexpr bool is = std::is_same<std::iterator_traits<It>::iterator_category, T>::value;
// quick sort
template <typename BidIt, typename Pred>
void qsort(BidIt first, BidIt last, Pred compare) noexcept
{
static_assert(is<BidIt, std::bidirectional_iterator_tag> || is<BidIt, std::random_access_iterator_tag>,
"bidirectional iterator required");
auto size = std::distance(first, last);
if (size > 1) {
using content_type = std::iterator_traits<BidIt>::value_type;
content_type pivot = *first;
std::vector<content_type> left(size), right(size);
auto left_end = left.begin();
auto right_end = right.begin();
for (BidIt i = std::next(first); i != last; ++i) {
compare(*i, pivot) ? *left_end++ = *i : *right_end++ = *i;
}
qsort(left.begin(), left_end, compare);
qsort(right.begin(), right_end, compare);
std::copy(left.begin(), left_end, first);
*std::next(first, std::distance(left.begin(), left_end)) = pivot;
std::copy(right.begin(), right_end, std::next(first, std::distance(left.begin(), left_end) + 1));
}
}你的想法?
发布于 2017-06-11 13:43:02
您可以节省一些缩进空间:
if (size > 1) {
... // Lots of code.
}至
if (size < 2) {
return;
}
... // Lots of code here.您可以就地进行分区;不需要要求更多的内存。维基百科中的伪代码相当详细,不使用任何辅助内存(当然,递归堆栈除外),并且易于理解。
发布于 2017-06-11 21:12:19
<iterator>,<type_traits>和<vector>。我的变更用<vector>换<algorithm>。typename将相依类型标记为类型。noexcept有点过了?#include <iterator>
#include <type_traits>
#include <algorithm>
// quick sort
template <typename BidIt, typename Pred
= std::less<typename std::iterator_traits<BidIt>::value_type>>
void qsort(BidIt first, BidIt last, Pred compare = {})
noexcept(noexcept(compare(*first, *first), std::iter_swap(first, first)))
{
static_assert(std::is_base_of<std::bidirectional_iterator_tag,
typename std::iterator_traits<BidIt>::iterator_category>(),
"at least bidirectional iterator required");
if (first == last || first == last - 1)
return;
const auto& pivot = *first;
auto left = first; ++left;
auto right = last;
do {
do --right;
while (left != right && !compare(*right, pivot));
while (left != right && compare(*left, pivot))
++left;
if (left != right) {
std::iter_swap(left, right);
++left;
}
} while (left != right);
std::iter_swap(first, left - 1);
qsort(first, left - 1, compare);
qsort(left, last, compare);
}发布于 2017-06-11 18:30:50
一般注意:std::sort()实现从libc++到libstdc++各不相同,但一般来说,它们要复杂得多。这个职位对你来说可能很有趣。
left和right构造)。Pred默认为std::less<> (或为C++11键入一个),并使compare默认为默认构造模板<.,typename Pred = std::less<>> .(.,Pred compare = {}) {.}typename之前需要std::iterator_traits<BidIt>::iterator_category,因为iterator_category是一个依赖类型。使用演示的完整代码:
#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <functional>
// iterator check
template <typename It, typename T>
constexpr bool is = std::is_same<typename std::iterator_traits<It>::iterator_category, T>::value;
// quick sort
template <typename BidIt, typename Pred = typename std::less<typename std::iterator_traits<BidIt>::value_type>>
void qsort(BidIt first, BidIt last, Pred compare = {}) noexcept
{
static_assert(is<BidIt, std::bidirectional_iterator_tag> || is<BidIt, std::random_access_iterator_tag>,
"at least bidirectional iterator required");
auto size = std::distance(first, last);
if (size > 1) {
using content_type = typename std::iterator_traits<BidIt>::value_type;
content_type pivot = *first;
std::vector<content_type> left, right;
left.reserve(size);
right.reserve(size);
auto left_end = std::back_inserter(left);
auto right_end = std::back_inserter(right);
for (BidIt i = std::next(first); i != last; ++i) {
compare(*i, pivot) ? *left_end++ = *i : *right_end++ = *i;
}
qsort(left.begin(), left.end(), compare);
qsort(right.begin(), right.end(), compare);
std::copy(left.begin(), left.end(), first);
*std::next(first, std::distance(left.begin(), left.end())) = pivot;
std::copy(right.begin(), right.end(), std::next(first, std::distance(left.begin(), left.end()) + 1));
}
}
struct integer
{
integer() = delete; //not default constructible
integer(int y):
x(y)
{}
int x;
};
bool operator<(const integer& lhs, const integer& rhs)
{
return lhs.x < rhs.x;
}
std::ostream& operator<<(std::ostream& os, const integer& x)
{
os << x.x;
return os;
}
int main() {
std::vector<integer> v{1, 0, -1, 4, 2};
qsort(v.begin(), v.end());
std::copy(v.begin(), v.end(), std::ostream_iterator<integer>(std::cout, " "));
}https://codereview.stackexchange.com/questions/165479
复制相似问题