STL基础——sort函数
关于快速排序
快速排序想必大家都知道,快排应该是各种排序算法中最普遍的了,因为它好打并且效率也挺高,平均时间复杂度为 Θ ( n log n ) \Theta(n\log_n) Θ(nlogn),这是基于比较的排序方法时间下限。
相信大多数情况下,大家是这么写快排的:
#include<bits/stdc++.h>
using namespace std;
int n,a[100001];
void qsort(int l,int r)
{
int mid=a[(l+r)/2],i=l,j=r;
do
{
while(a[i]<mid) i++;
while(a[j]>mid) j--;
if(i<=j)
{
swap(a[i],a[j]);
i++;
j--;
}
}while(i<=j);
if(l<j) qsort(l,j);
if(i<r) qsort(i,r);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
qsort(1,n);
for(int i=1;i<=n;i++)
printf("%d ",a[i]);
return 0;
}
但是!快排有一个很大的缺点,易退化,出题人只要想卡以上这种快排,针对性造几组数据就可以了。
比如这道题,如果你提交以上代码,得到的结果肯定是
TLE
\colorbox{black}{\color{white}{TLE}}
TLE
为什么呢会超时呢?因为如果数据是单调递减序列,快速排序就会退化为
O
(
n
)
O(n)
O(n)的冒泡排序
听不懂的可以看看这张图辅助理解(个人认为这张图直观且明了):
所以归并是神!
当然,快速排序也是有优化的,比如说三路快速排序,内省排序等
懂了,所以怎么实现?
但这些都不重要,接下来就请出我们的主角——STL!
STL探幽
什么是STL
从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其他一些组件的集合。这里的“容器”和算法的集合指的是世界上很多聪明人很多年的杰作。STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件。STL是C++的一部分,因此不用安装额外的库文件。——百度百科
反正好用就对了
STL基础——sort
既然说STL中有许多好用的模板,那么肯定少不了sort,如果你用下面的代码提交上面的模板题,肯定能A
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int a[n];
for(int i=0;i<n;i++)
{
cin>>a[i];
}
sort(a,a+n);
for(int i=0;i<n;i++)
{
cout<<a[i]<<" ";
}
return 0;
}
怎么样,是不是很神奇?一个sort函数就能帮你省略这么多代码,而且效率异常的高,为什么呢?
因为从 2000 年 6 月起,SGI C++ STL 的 stl_algo.h 中 sort() 函数的实现采用了内省排序算法。
内省排序(英语:Introsort 或 Introspective sort)是快速排序和 堆排序 的结合,由 David Musser 于 1997 年发明。内省排序其实是对快速排序的一种优化,保证了最差时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)。
内省排序将快速排序的最大递归深度限制为 ,超过限制时就转换为堆排序。这样既保留了快速排序内存访问的局部性,又可以防止快速排序在某些情况下性能退化为 O ( n 2 ) O(n^2) O(n2)。——OI wiki
所以说,sort简单好用且高效!
sort的食用方法
sort虽然是神器,但也要学会用才能让它发挥威力。
我们来看看它的函数原型:
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);