C++ STL中sort简单理解

本文介绍了C++ STL中的sort函数,详细讲解了sort的实现原理,包括内省式排序(IntroSort)如何在快排性能下降时切换至堆排序,确保O(nlgn)的时间复杂度。同时,文章提及了sort与其他排序函数如stable_sort、partial_sort的区别,并提供了sort在不同容器中的适用情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

0、学完《数据结构》课程后,了解到排序的多种算法,例如堆排序、快速排序、直接排序、归并排序等。同样我们使用c++标准库中sort()可以避免我们直接动手写一个排序的算法从而简单的达到我们所需要的效果。

思考一个问题:sort()使用的是哪种排序算法?

 

1、sort()实现的详解

1.1函数声明

#include <algorithm>



template< class RandomIt >

void sort( RandomIt first, RandomIt last );



template< class RandomIt, class Compare >

void sort( RandomIt first, RandomIt last, Compare comp );

stl提供两种调用sort()的方式,一是使用默认的 < 操作符比较,二是自定义比较函数方式。

bool operator < (const class &m)const {

                return first < m.first;

        }//运算符重载

bool less_second(const class & m1, const class & m2) {

        return m1.second < m2.second;

}

1.2算法实现原理

STL中的sort不是普通的快速排序,更是对普通的快速排序进行优化,它还结合了插入排序和堆排序。根据不同的数量级别以及不同情况,能自动选用合适的排序方法。当数据量较大时采用快速排序,分段递归。一旦分段后的数据量小于某个阀值,为避免递归调用带来过大的额外负荷,便会改用插入排序。而如果递归层次过深,有出现最坏情况的倾向,还会改用堆排序。

普通的快速排序,每次选定第一个元素为基准元素将排序码分为前后两个子块,循环下去,直到排序完成。简单来说就是从中间到两端的排序。一般情况下时间复杂度是O(nlbn),但基准元素的选择不当即导致分割的子块不当,时间复杂度会恶化到O(n*n)。

1.3内省式排序 introsort

为了避免这种情况,David R.Musser于1996年提出一种混合式排序算法:Introspective Sorting(内省式排序),简称IntroSort,其行为大部分与上面所说的median-of-three Quick Sort完全相同,但是当分割行为有恶化为二次方的倾向时,能够自我侦测,转而改用堆排序,使效率维持在堆排序的 O(nlgn),又比一开始就使用堆排序来得好。

 

2、代码展示

下面是完整的SGI STL sort()源码(使用默认<操作符版)

template <class _RandomAccessIter>

inline void sort(_RandomAccessIter __first, _RandomAccessIter __last) {

  __STL_REQUIRES(_RandomAccessIter, _Mutable_RandomAccessIterator);

  __STL_REQUIRES(typename iterator_traits<_RandomAccessIter>::value_type,

                 _LessThanComparable);

  if (__first != __last) {

    __introsort_loop(__first, __last,

                     __VALUE_TYPE(__first),

                     __lg(__last - __first) * 2);

    __final_insertion_sort(__first, __last);

  }

}

其中,__introsort_loop便是上面介绍的内省式排序,其第三个参数中所调用的函数__lg()便是用来控制分割恶化情况,代码如下:

template <class Size>

inline Size __lg(Size n) {

    Size k;

    for (k = 0; n > 1; n >>= 1) ++k;

    return k;

}

即求lg(n)(取下整),意味着快速排序的递归调用最多 2*lg(n) 层。

内省式排序算法如下:

template <class _RandomAccessIter, class _Tp, class _Size>

void __introsort_loop(_RandomAccessIter __first,

                      _RandomAccessIter __last, _Tp*,

                      _Size __depth_limit)

{

  while (__last - __first > __stl_threshold) {

    if (__depth_limit == 0) {

      partial_sort(__first, __last, __last);

      return;

    }

    --__depth_limit;

    _RandomAccessIter __cut =

      __unguarded_partition(__first, __last,

                            _Tp(__median(*__first,

                                         *(__first + (__last - __first)/2),

                                         *(__last - 1))));

    __introsort_loop(__cut, __last, (_Tp*) 0, __depth_limit);

    __last = __cut;

  }

}
  1. ######对代码还是不太理解,虽然理解sort()使用的算法。#########
  2.  
  3. 3、所有sort算法和sort中的比较函数介绍
  4. 3.1 sort算法
  5. 1)sort()
  6. 2)stable_sort()//stable_sort的稳定性比sort强
  7. 3)partial_sort()
  8. 4)partial_sort_copy()
  9. 5)nth_element()//找出给定区间的某个位置对应的元素
  10. 6)is_sorted()
  11. 7)partition()
  12. 8)stable_partition()
  13. 3.2 比较函数
  14. equal_to
  15. not_equal_to
  16. less
  17. less_equal等
  18.  
  19. 4、sort和容器
  20. 标准模版库的标准容器主要有vector,list,deque,map,set,string,stack,queue,
  21. multimap等。其中map,multimap,multiset是以树形结构存储数据,所以sort不可用。

述sort函数对于下列容器是可用的:

  • vector
  • string
  • deque
  • 5、合适的排序函数
  • 如果数据很小,可以不考虑程序运行的效率,但当数据非常
  • 大。
  • 这是就要考虑到程序执行的效率,选择合理的排序函数会节省大
  • 量的时间。
  • 从效率上看,以下几种sort算法的是一个排序,效率由高到低(耗时由小变大):
  • partion
  • stable_partition
  • nth_element
  • partial_sort
  • sort
  • stable_sort

《Effective STL》对如何选择排序函数的总结摘取了一条:

若需对vector, string, deque, 或 array容器进行全排序,你可选择sort或stable_sort;

 

参考文献

1、《Effective STL》中文版

2《STL源码剖析》 作者:侯捷

3、http://blog.youkuaiyun.com/bz201/article/details/543001

4、https://www.cnblogs.com/fengcc/p/5256337.html

世界地图矢量数据可以通过多种网站进行下载。以下是一些提供免费下载世界地图矢量数据的网站: 1. Open Street Map (https://www.openstreetmap.org/): 这个网站可以根据输入的经纬度或手动选定范围来导出目标区域的矢量图。导出的数据格式为osm格式,但只支持矩形范围的地图下载。 2. Geofabrik (http://download.geofabrik.de/): Geofabrik提供按洲际和国家快速下载全国范围的地图数据数据格式支持shape文件格式,包含多个独立图层,如道路、建筑、水域、交通、土地利用分类、自然景观等。数据每天更新一次。 3. bbbike (https://download.bbbike.org/osm/): bbbike提供全球主要的200多个城市的地图数据下载,也可以按照bbox进行下载。该网站还提供全球数据数据格式种类齐全,包括geojson、shp等。 4. GADM (https://gadm.org/index.html): GADM提供按国家或全球下载地图数据的服务。该网站提供多种格式的数据下载。 5. L7 AntV (https://l7.antv.antgroup.com/custom/tools/worldmap): L7 AntV是一个提供标准世界地图矢量数据免费下载的网站。支持多种数据格式下载,包括GeoJSON、KML、JSON、TopJSON、CSV和高清SVG格式等。可以下载中国省、市、县的矢量边界和世界各个国家的矢量边界数据。 以上这些网站都提供了世界地图矢量数据免费下载服务,你可以根据自己的需求选择合适的网站进行下载
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值