小王职场记STL(2)std:sort解析

上篇文章回顾:

小王职场记 谈谈你的STL理解(1)


std:sort代码解析 开始

首先看一段视频。
https://www.youtube.com/watch?v=67ta5WTjjUo

然后看一段代码会有什么问题。

std:sort

当数据元素相同时候
stl sort会概率造成core dump(如果你测试,不一定会重现 ,猜一下需要什么条件?)

image.png

一、问题
std::sort()在排序的时候,如果对排序中的仿函数对相等的值返回true,会导致程序core掉。

二、解决办法
让比较函数对相等的值返回false

三、原因分析std:sort 分析
完整版请看:
文档注释:https://github.com/wangcy6/weekly/blob/master/stl.md
代码注释:https://github.com/wangcy6/weekly/blob/master/KM/code/stl_algo.h

版本

gcc 使用 4.8.4 版本,STL源码 在 Linux 系统的位置是:/usr/include/c++/4.8.4/bits (79个文件)

目录:

小王职场记 谈谈你的STL理解(1)

函数对象模块

  • 定义:

    重载了“operaotr()”操作符的普通类对象 ,

    这个对象具备了具有函数行为

    调用类(), 相当于调用类.成员函数()


 // 大于
template <class _Tp>
struct greater : public binary_function<_Tp,_Tp,bool> 
{
  bool operator()(const _Tp& __x, const _Tp& __y) const { return __x > __y; }
};
//这个函数对象没有数据成员、没有虚函数、没有显示声明的构造函数和析构函数,且对operator()的实现是内联的。用作STL比较器的函数对象一般都很小

greater<int> greaterobj;
greaterobj(3, 5)//等价于greaterobj.operator(3,5) 效果等价于函数调用function(3, 5); 

    

算法部分

代码:

stl_algo.h

std:compare:

Effective STL: Item 21:永远让比较函数对相同元素返回false

std: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); //剩下未排序的数据,直接插入排序
    
  }
}
template <class _RandomAccessIter, class _Tp, class _Size>
void __introsort_loop(_RandomAccessIter __first,
                      _RandomAccessIter __last, _Tp*,
                      _Size __depth_limit)
{
  while (__last - __first > __stl_threshold) { ///长度大于16才进行一次快排分割
    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; //排前一部分
  }
}

std:sort描述

维基百科 内省排序

内省排序(英语:Introsort)是由David Musser在1997年设计的排序算法

  • 这个排序算法首先从快速排序开始,当递归深度超过一定深度(深度为排序元素数量的对数值)后转为堆排序。采用这个方法,

内省排序既能在常规数据集上实现快速排序的高性能,又能在最坏情况下仍保持{\displaystyle O(nlogn)}[图片上传失败...(image-b3b9a4-1548141339074)]的时间复杂度。由于这两种算法都属于比较排序算法,所以内省排序也是一个比较排序算法。

  • 2000年6月,SGI的C++标准模板库stl_algo.h中的不稳定排序算法采用了Musser的内省排序算法。在此实现中,切换到插入排序的数据量阈值为16个。

主要因素:
if 递归深度 多大 then 改为堆排序 有不稳定排序改成稳定排序
if 数据少于16个 then 改为 插入排序,降低递归堆栈消耗

,因此Musser在1996年发表了一遍论文,提出了Introspective Sorting(内省式排序),这里可以找到PDF版本。它是一种混合式的排序算法,集成了前面提到的三种算法各自的优点:

  • 在数据量很大时采用正常的快速排序,此时效率为O(logN)。

  • 一旦分段后的数据量小于某个阈值,就改用插入排序,因为此时这个分段是基本有序的,这时效率可达O(N)。

  • 在递归过程中,如果递归层次过深,分割行为有恶化倾向时,它能够自动侦测出来,使用堆排序来处理,在此情况下,使其效率维持在堆排序的O(N logN),但这又比一开始使用堆排序好。

复杂度

image.png

参考

  1. http://feihu.me/blog/2014/sgi-std-sort/
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 228,546评论 6 533
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,570评论 3 418
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 176,505评论 0 376
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,017评论 1 313
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,786评论 6 410
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,219评论 1 324
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,287评论 3 441
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,438评论 0 288
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,971评论 1 335
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,796评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,995评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,540评论 5 359
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,230评论 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,662评论 0 26
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,918评论 1 286
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,697评论 3 392
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,991评论 2 374

推荐阅读更多精彩内容

  • 原文地址:https://blog.csdn.net/bamboolsu/article/details/4645...
    Caiaolun阅读 1,808评论 0 1
  • qsort vs std::sort 朋友问我,qsort和std::sort有什么区别,我没有专门查过,但还是尝...
    先点菜吧阅读 5,262评论 2 2
  • 总结一下常见的排序算法。 排序分内排序和外排序。内排序:指在排序期间数据对象全部存放在内存的排序。外排序:指在排序...
    jiangliang阅读 1,364评论 0 1
  • 原文链接:http://net.pku.edu.cn/~yhf/UsingSTL.htm 三十分钟掌握STL这是本...
    Transnet2014阅读 1,094评论 0 10
  • 文:蝈蝈 图片编辑:蝈蝈 一、有这么一群人在打拼着,他们虽卑微,却也是一束光,一束为自己闪耀的微光。 城市给人第一...
    ICE蝈蝈阅读 457评论 1 3