std::sort() 中使用哪种类型的排序?

发布于 2024-08-13 04:14:06 字数 95 浏览 2 评论 0原文

谁能告诉我在 std::sort() 函数中实现了哪种类型的排序技术(冒泡、插入、选择、快速、合并、计数...) ><算法>头文件?

Can anyone please tell me that which type of sorting technique (bubble, insertion, selection, quick, merge, count...) is implemented in the std::sort() function defined in the <algorithm> header file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

旧时模样 2024-08-20 04:14:06

std::sort 的大多数实现都使用快速排序(或者通常是像 introsort 这样的混合算法,它结合了快速排序、堆排序和插入排序)。

标准唯一要求的是 std::sort 以某种方式根据指定的顺序对数据进行排序,复杂度约为 O(N log(N));不保证稳定。从技术上讲,内推排序比快速排序更好地满足复杂性要求,因为快速排序的最坏情况时间是二次的。

Most implementations of std::sort use quicksort, (or usually a hybrid algorithm like introsort, which combines quicksort, heapsort and insertion sort).

The only thing the standard requires is that std::sort somehow sort the data according to the specified ordering with a complexity of approximately O(N log(N)); it is not guaranteed to be stable. Technically, introsort better meets the complexity requirement than quicksort, because quicksort has quadratic worst-case time.

無心 2024-08-20 04:14:06

C++ 标准 ISO/IEC 14882:2003

25.3.1.1排序

模板
   void sort(RandomAccessIterator 首先,RandomAccessIterator 最后);
模板<类RandomAccessIterator,类比较>
   void sort(RandomAccessIterator 首先,RandomAccessIterator 最后,
          比较比较);

1 效果:对元素进行排序
范围[第一个,最后一个)。

2 复杂性
大约 N log N(其中 N == 最后一个
- 第一)平均比较。

没有有关方法的信息,但复杂性始终为N log N

C++ Standard ISO/IEC 14882:2003

25.3.1.1 sort

template<class RandomAccessIterator>
   void sort(RandomAccessIterator first, RandomAccessIterator last);
template<class RandomAccessIterator, class Compare>
   void sort(RandomAccessIterator first, RandomAccessIterator last,
          Compare comp);

1 Effects: Sorts the elements in the
range [first, last).

2 Complexity:
Approximately N log N (where N == last
- first) comparisons on the average.

There is no information about method but complexity is always N log N.

情深已缘浅 2024-08-20 04:14:06

MSVC2013 STL中使用了三种算法,参考std::sort源码。

它最有可能使用 QuickSort,或 QuickSort 的变体,称为 IntroSort

如果递归太深,这里将使用HeapSort

否则将使用InsertSort

There are three algorithms that are used in MSVC2013 STL, referring to the source code of std::sort.

It is most likely to use QuickSort, or a variation over QuickSort called IntroSort.

If the recursion goes too deep, the HeapSort will be used here.

Otherwise InsertSort will be used.

满天都是小星星 2024-08-20 04:14:06

可能 std::sort 的所有实现都使用 introsort(又名内省排序),这是一种结合了快速排序和堆排序的混合算法。实际上,introsort 是在 1997 年专门发明的,目的是在 C++ STL 中实现高性能排序。

标准唯一要求的是 std::sort 以某种方式根据指定的顺序对数据进行排序,复杂度为 O(N log(N));它不保证稳定(如果需要的话,可以使用单独的 std::stable_sort 算法)。

从技术上讲,introsort 比快速排序更能满足复杂性要求:这是因为堆排序在最坏情况下保证了 O(N log(N)) 复杂性,而快速排序在最坏情况下的时间是二次方。

然而,在一般情况下,堆排序比快速排序“慢”,因为堆排序执行C*N log(N),而快速排序执行D*N log(n) > 性能,D 明显小于 C(数字 CD 是常数)。换句话说,堆排序的每次比较开销高于快速排序。

为了获得两全其美的效果,introsort 从快速排序(一种递归算法)开始,但是当递归深度变得太高时(这意味着它会陷入退化最坏情况的行为),它会切换到堆排序。

另请参阅introsort 的 Wikipedia 条目来自 David Musser 的原始论文,他专门为 STL 发明了 introsort。

Probably all implementations of std::sort use introsort (aka introspection sort), a hybrid algorithm that combines quicksort and heapsort. Actually, introsort was particularly invented in 1997 for the purpose of a performant sort implemenation in C++ STL.

The only thing the standard requires is that std::sort somehow sort the data according to the specified ordering with a complexity of O(N log(N)); it is not guaranteed to be stable (there is a separate std::stable_sort algorithms available, if this should be required).

Technically, introsort better meets the complexity requirement than quicksort: This is because heapsort has guaranteed O(N log(N)) complexity in the worst case, whereas quicksort has quadratic worst-case time.

However, heapsort is 'slower' than quicksort in the average case, in the sense that heapsort performs C*N log(N) whereas quicksort has D*N log(n) performance, with D being significantly smaller than C (the numbers C and D are constants). In other words, the per-comparison-overhead of heapsort is higher than the one of quicksort.

To get the best of both worlds, introsort starts with quicksort —a recursive algorithm—, but when recursion depth gets too high (which means it gets into a degenerated worst-case behaviour), it switches to heapsort.

See also the Wikipedia entry for introsort or the original paper from David Musser, who invented introsort particularly for STL.

往事风中埋 2024-08-20 04:14:06

GCC 9.2.0 libstdc++ 源确认 introsort

其他提到了 introsort,但这里有一些证据libstc++,这是大多数 Linux 发行版上的默认 C++ 实现。

libstdc++ 是 GCC 本身的一部分,因此我们将研究 GCC 源代码。

libstdc++- v3/include/std/algorithm 是主标头,包含:

#include <bits/stl_algobase.h>
#include <bits/stl_algo.h>

然后, bits/stl_algo.h 包含排序重载的定义,其中之一是:

  /**
   *  @brief Sort the elements of a sequence.
   *  @ingroup sorting_algorithms
   *  @param  __first   An iterator.
   *  @param  __last    Another iterator.
   *  @return  Nothing.
   *
   *  Sorts the elements in the range @p [__first,__last) in ascending order,
   *  such that for each iterator @e i in the range @p [__first,__last-1),  
   *  *(i+1)<*i is false.
   *
   *  The relative ordering of equivalent elements is not preserved, use
   *  @p stable_sort() if this is needed.
  */
  template<typename _RandomAccessIterator>
    inline void
    sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
    {
      // concept requirements
      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
        _RandomAccessIterator>)
      __glibcxx_function_requires(_LessThanComparableConcept<
        typename iterator_traits<_RandomAccessIterator>::value_type>)
      __glibcxx_requires_valid_range(__first, __last);
      __glibcxx_requires_irreflexive(__first, __last);

      std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
    }

所以我们看到这只是对输入进行一系列健全性检查,然后调用 std::__sort ,即 在同一个文件中定义

  template<typename _RandomAccessIterator, typename _Compare>
    inline void
    __sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
       _Compare __comp)
    {
      if (__first != __last)
    {
      std::__introsort_loop(__first, __last,
                std::__lg(__last - __first) * 2,
                __comp);
      std::__final_insertion_sort(__first, __last, __comp);
    }
    }

我们已经到达了一个标识符称为 std::__introsort_loop ,其余的实现位于同一个文件上,任何人仍然有疑问。

在 Ubuntu 18.04 中,也应该可以将 GDB 单步调试到 std::sort 中,而无需进行任何进一步的设置,如 std::set 中所述:STL集的底层数据结构是什么在 C++ 中?

C++17 并行排序

我们现在也有并行排序,因此也值得研究一下它是如何完成的:C++17 并行算法已经实现了吗?

正如上面的答案中提到的,实现依赖于外部库:英特尔线程构建模块:https://github.com/intel/tbb

GCC 9.2.0 libstdc++ source confirming introsort

Others have mentioned introsort, but here is some evidence for libstc++, which is the default C++ implementation on most Linux distros.

libstdc++ is a part of GCC itself, so we will look into GCC source.

libstdc++-v3/include/std/algorithm is the main header and contains:

#include <bits/stl_algobase.h>
#include <bits/stl_algo.h>

Then, bits/stl_algo.h contains the definition of the sort overloads, one of them being:

  /**
   *  @brief Sort the elements of a sequence.
   *  @ingroup sorting_algorithms
   *  @param  __first   An iterator.
   *  @param  __last    Another iterator.
   *  @return  Nothing.
   *
   *  Sorts the elements in the range @p [__first,__last) in ascending order,
   *  such that for each iterator @e i in the range @p [__first,__last-1),  
   *  *(i+1)<*i is false.
   *
   *  The relative ordering of equivalent elements is not preserved, use
   *  @p stable_sort() if this is needed.
  */
  template<typename _RandomAccessIterator>
    inline void
    sort(_RandomAccessIterator __first, _RandomAccessIterator __last)
    {
      // concept requirements
      __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
        _RandomAccessIterator>)
      __glibcxx_function_requires(_LessThanComparableConcept<
        typename iterator_traits<_RandomAccessIterator>::value_type>)
      __glibcxx_requires_valid_range(__first, __last);
      __glibcxx_requires_irreflexive(__first, __last);

      std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter());
    }

so we see that this just does a bunch of sanity checks on the input, and then calls std::__sort which is defined in the same file:

  template<typename _RandomAccessIterator, typename _Compare>
    inline void
    __sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
       _Compare __comp)
    {
      if (__first != __last)
    {
      std::__introsort_loop(__first, __last,
                std::__lg(__last - __first) * 2,
                __comp);
      std::__final_insertion_sort(__first, __last, __comp);
    }
    }

and I'll stop here that we have reached an identifier called std::__introsort_loop, the rest of the implementation is on the same file is anyone still has doubts.

It should also be possible to GDB step debug into std::sort without any further setup in Ubuntu 18.04 as mentioned for std::set at: What is the underlying data structure of a STL set in C++?

C++17 parallel sorting

We now also have parallel sorting, so it would be worth looking on how it is done as well: Are C++17 Parallel Algorithms implemented already?

As mentioned in the above answer, the implementation relies on an external library: Intel Thread Building Blocks: https://github.com/intel/tbb

合约呢 2024-08-20 04:14:06

您的意思是 std::sort 吗?如果是这样,就可以按照他们想要的任何方式实施。它可能是快速排序,但也可能是基数或其他东西。据我所知,只要它能在至少 O(n log n) 内生成一个排序列表,实现就可以了。

Do you mean std::sort? If so it can be implemented any way they want. Its probably Quick sort but could be radix or something else. As long as it produces you a sorted list in at least O(n log n) the implementation is fine, afaik.

月寒剑心 2024-08-20 04:14:06

只是一些经验结果:

我使用 std::sort (VS2008 工具链)将使用 numpy 1.9.2 sort 的 python 脚本翻译为 C++。

当我使用 numpy.sort 参数 kind='mergesort' 时,我只能在 python 和 C++ 方面得到相同的精确结果。当 kind='quicksort' 或 kind='heapsort' 时,具有相同键的元素的相对顺序不同。所以我猜想至少对于VS2008 std::sort自带的STL版本来说是使用mergesort的。

Just some empirical results:

I translated a python script using numpy 1.9.2 sort to C++ using std::sort (VS2008 toolchain).

I only get the same exact results in the python and C++ sides when I use numpy.sort argument kind='mergesort'. I get different relative ordering for elements with same key when kind='quicksort' or kind='heapsort'. So I guess that at least for the version of STL that comes with VS2008 std::sort uses mergesort.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文