首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >现代C++兼容插入排序

现代C++兼容插入排序
EN

Code Review用户
提问于 2015-04-26 23:20:52
回答 2查看 749关注 0票数 4

这是对我以前的排序实现问题的一种后续,特别是插入排序和现代C++成语。任何看到这篇文章的人都可以看到,我是如何获得一种典型的C风格分类的,你可以通过访问我以前的分类评论在网上到处找到。

作为一次面试的回顾,我正在撰写我以前见过的符合现代C++的排序算法版本。这篇文章是关于插入排序和插入排序的。

代码语言:javascript
复制
// Shift/bubble each element toward the front into a sorted sub-array
template<typename BdIterator, typename Comparator = std::less<typename std::iterator_traits<BdIterator>::value_type>>
void sort_insertion(BdIterator beg, BdIterator end, Comparator cmp = Comparator())
{
    BdIterator front, cur, prev;
    // Assume the first element is sorted.
    for (front = beg + 1u; front != end; ++front)
    {
        cur = front;
        prev = cur - 1u;
        // Bubble the "next" element towards the front by swapping it with its 
        // "prev" neighbor until it is in its sorted position.
        while (cur != beg && cmp(*cur, *prev))
            std::iter_swap(cur--, prev--);
    }
}

和以前一样,我正在寻找算法本身可能遗漏的任何性能优化,以及本例中可能没有遵守的现代C++结构。

一个具体的问题是,我要处理的是我正在添加和减去的无符号整数,以便移动到容器中的下一个和以前的值。由于无法获得所提供的迭代器的容器类型,所以我看不到一种方法可以使假定容器的size_type添加和减去正确的类型,而不仅仅是无符号/有符号整数。

我正在减去的事实阻止了我将最小Iterator模板类型声明为前向迭代器(我们正在向后移动迭代器)。是否有更好的方法来解决这个问题,还是我应该坚持做最低限度的BiDirectionalIterators?

EN

回答 2

Code Review用户

回答已采纳

发布于 2015-04-27 00:54:54

“我要问的一个具体问题是,我正在添加和减去迭代器中的无符号整数,以移动到容器中的下一个值和前一个值。由于无法获得所提供的迭代器的容器类型,所以我看不到获得假定容器的size_type来添加和减去正确类型的方法,而不仅仅是无符号/有符号整数。”

我刚刚发现std::prevstd::next是在#include 中定义的,我认为这将处理一些签名/无符号不匹配的情况。

对于需要执行更复杂的算术(例如除法或乘法)的其他情况,您可以使用:

代码语言:javascript
复制
std::iterator_traits<BdIterator>::difference_type

std::distance返回std::iterator_traits<BdIterator>::difference_type

std::nextstd::prevstd::iterator_traits<BdIterator>::difference_type为参数。双向迭代器上的算法可能会倒退。

“我正在减去的事实阻止了我将最小的Iterator模板类型声明为前向迭代器(我们正在向后移动迭代器)。有什么更好的方法来解决这个问题,还是我应该坚持做最小的BiDirectionalIterators呢?”

我没有意识到,无论我是否使用std::prev,算法本身都依赖于向前和向后移动迭代器,因此需要BiDirectional迭代器。

有一个更有效的解决方案,它依赖于找到一个洞并鼓起这个孔,然后将值插入到它的排序孔中。

代码语言:javascript
复制
// Shift/bubble each element toward the front into a sorted sub-array
template<typename BidirIt, typename Comparator = std::less<typename std::iterator_traits<BidirIt>::value_type>>
void sort_insertion(BidirIt first, BidirIt last, Comparator cmp = Comparator())
{
    using category = typename std::iterator_traits<BidirIt>::iterator_category;
    static_assert(std::is_base_of<std::bidirectional_iterator_tag, category>::value, "This algorithm requires bidirectional iterators.");

    // 1 element containers are sorted; 2 duplicate element containers are sorted.
    if (first != last)
    {
        // Make a hole by removing the element you are checking,
        // and move elements up to that hole until you find the correct position of the element removed.
        // ++cur: Assume the first element is sorted.
        for (BidirIt cur = first; ++cur != last;)
        {
            auto val = std::move(*cur);
            BidirIt next = cur, prev = std::prev(next);
            while (cmp(val, *prev))
            {
                *next = std::move(*prev);
                next = prev;
                if (prev != first) --prev;
                else break;
            }
            // insert value in its sorted hole.
            *next = std::move(val);
        }
    }
}
票数 2
EN

Code Review用户

发布于 2015-11-15 10:49:00

专注于使用<algorithm>作为更大功能的构建块。在使用双向迭代器进行插入排序的情况下,可以将查找插入点的逻辑与移位分离。

代码语言:javascript
复制
template <class BidirIt, class Compare = std::less<>>
void insertion_sort(BidirIt first, BidirIt last, Compare cmp = Compare{}) {
  if (first == last || std::next(first) == last) {
    return;
  }

  using RevIt = std::reverse_iterator<BidirIt>;
  for (auto curr = std::next(first); curr != last; ++curr) {
    // Reverse Linear Search the insertion point
    const auto insertion =
        std::find_if_not(RevIt(curr), RevIt(first), [=](const auto& elem) {
          return cmp(*curr, elem);
        }).base();

    auto elem = std::move(*curr);
    std::move_backward(insertion, curr, std::next(curr));
    *insertion = std::move(elem);
  }
}
票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/88075

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档