std::sort为什么保证严格弱序?
这个问题是面试腾讯光子的时候面试官提的,当时的问题是:sort自定义comp函数能用>=吗?当时的我想comp函数只要函数签名是对的应该就没问题吧,于是答了可以。面试结束后总感觉哪里不对,耿耿于怀,几番搜寻也只找到说要保证严格弱序,原理网上基本却没有。只能求助于源码了,打开<<STL源码剖析>>,看了一遍sort的实现,还是没能找出问题所在(这里要给自己提个醒,思考得不够)。我不服,又在网上搜索了一遍结合源码,终于找到了答案。
首先补充一下满足严格弱序的3个条件:
1.两个关键字不能同时严格弱序于对方。
2.如果a严格弱序于b,且b严格弱序于c,则a必须严格弱序于c。
3.如果存在两个关键字,任何一个都不严格弱序于另一个,则这两个关键字是相等的。
sort采用的排序算法是IntroSort,是一种混合型算法。简单来说就是利用快排将要排序的数组分隔成大致有序的几段, 根据递归深度和分隔开的小段长度情况看是否采取堆排序,最后再进行插入排序。这样的话能在最坏情况下将时间复杂度推进到O(nlogn)。在SGISTL实现的插入排序是这么写的:
void __unguarded_linear_insert(RandomAccessIterator last, T value)
{
RandomAccessIterator next = last;
--next;
while(value < *next)
{
*last = *next;
last = next;
--next;
}
*last = value;
}
将注意力放在第5行的while循环上,你会发现这里并没有判断边界,原因是stl以严格弱序为前提且在进入这个函数前会保证有哨兵在数组的前方。(这里代码是直接使用的小于,使用自定义comp的时候将while里的<判断换成comp理解就可以了。)
那么如果我们元素不严格弱序的话,在全是相等元素的情况下,这个while会无限循环下去,最终造成数组越界!
其实不止在插入排序这块,在快速排序进行分割的时候也会出现类似的问题,这里就不再多说了。
std::sort为什么保证严格弱序?的更多相关文章
- 将三维空间的点按照座标排序(兼谈为std::sort写compare function的注意事项)
最近碰到这样一个问题:我们从文件里读入了一组三维空间的点,其中有些点的X,Y,Z座标只存在微小的差别,远小于我们后续数据处理的精度,可以认为它们是重复的.所以我们要把这些重复的点去掉.因为数据量不大, ...
- 源码阅读笔记 - 1 MSVC2015中的std::sort
大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格 ...
- c++ std::sort函数调用经常出现的invalidate operator<错误原因以及解决方法
在c++编程中使用sort函数,自定义一个数据结构并进行排序时新手经常会碰到这种错误. 这是为什么呢?原因在于什么?如何解决? 看下面一个例子: int main(int, char*[]) { st ...
- 一个std::sort 自定义比较排序函数 crash的分析过程
两年未写总结博客,今天先来练练手,总结最近遇到的一个crash case. 注意:以下的分析都基于GCC4.4.6 一.解决crash 我们有一个复杂的排序,涉及到很多个因子,使用自定义排序函数的st ...
- 科普:std::sort干了什么
std::sort算是STL中对OIer比较友好的函数了,但你有想过sort是如何保证它的高速且稳定吗? 正文 我们首先来到第一层:sort函数 template<typename _Rando ...
- std::sort引发的core
#include <stdio.h> #include <vector> #include <algorithm> #include <new> str ...
- Qt使用std::sort进行排序
参考: https://blog.csdn.net/u013346007/article/details/81877755 https://www.linuxidc.com/Linux/2017-01 ...
- 非常无聊——STD::sort VS 基数排序
众所周知,Std::sort()是一个非常快速的排序算法,它基于快排,但又有所修改.一般来说用它就挺快的了,代码一行,时间复杂度O(nlogn)(难道不是大叫一声“老子要排序!!”就排好了么...). ...
- 今天遇到的一个诡异的core和解决 std::sort
其实昨天开发pds,就碰到了core,我还以为是内存不够的问题,或者其他问题. 今天把所有代码挪到了as这里,没想到又出core了. 根据直觉,我就觉得可能是std::sort这边的问题. 上网一搜, ...
随机推荐
- WinSCP整合SecureCRT打开终端
使用WinSCP直接操作文件非常方便,但是如果用它来连入SSH进行指令交互就不方便了,使用XShell.SecureCRT.Putty等SSH终端软件敲指令却很不错,于是想能不能将两者结合起来使用.我 ...
- python笔记11
今日内容 函数小高级 lambda 表达式 内置函数 内容回顾 函数基本结构 参数 形参 基本参数:def func(a1,a2):pass 默认值:def func(a1,a2=123):pass ...
- Spring Cache 抽象(缓存抽象) Redis 缓存
积少成多 ---- 仅以此致敬和我一样在慢慢前进的人儿 相关内容: https://blog.51cto.com/14230003/2369413?source=dra ...
- 【vue_django】成功登录后,保存用户
PS:使用session 保存: // 登录 login() { if (this.username === "" || this.password === "" ...
- PuTTYTabManager汉化版
PuTTY Tab Manager(puttytm) V0.52 zh_CN 简体中文汉化版 功能 Putty是一款小巧好用免费的SSH客户端工具,但是不支持多标签管理,网上找了一些相关的putty多 ...
- Spring注入bean的方式
在Spring容器中为一个bean配置依赖注入有三种方式: · 使用属性的setter方法注入 这是最常用的方式: · 使用构造器注入: · 使用Filed注入(用于注解方式). 使用属性的se ...
- JAVA&&JAVA WEB开发包U盘封装版
难以忍受机房的开发环境,就简单实现了将所有的开发文件封装进了U盘. 基于wmic的强大功能,实现了机房变态环境下的设置环境变量OS不用重新启动OS! install.bat @echo off mod ...
- HDU_2446_打表
http://acm.hdu.edu.cn/showproblem.php?pid=2446 打表,二分查找,注意查找最后的判断. #include<cstdio> #define N 2 ...
- IniRealm讲解
Shiro自定义Realm 内置Realm: user.ini [users] Mark=123456,admin [roles] admin=user:delete,user:update IniR ...
- 并发编程之Master-Worker模式
我们知道,单个线程计算是串行的,只有等上一个任务结束之后,才能执行下一个任务,所以执行效率是比较低的. 那么,如果用多线程执行任务,就可以在单位时间内执行更多的任务,而Master-Worker就是多 ...