C++STL排序算法

在介绍排序算法前,先说明一个可以称为排序准则的东西,也就是定义strict weak ordering,其意义如下:

1.必须是非对称的,对operator < 而言,如果x<y是true,则y<x为false。对判断式op()而言,若op(x,y)为true,则op(x,y)为false。

2.必须是可传递的,对operator < 而言,如果x<y是true且y<z为true,则x<z为true。对判断式op()而言,若op(x,y)为true且op(y,z)为true。

op(x,z)为true。

3.必须是非自反的,对operator < 而言,x<x永远是false。对判断式op()而言,op(x,x)永远为false。

4.必须具有等效传递性,大致上来说就是如果a==b&&b==c,那么a=c。

STL的排序算法

stl提供了几种算法来对区间内的元素排序,一般分为完全排序(full sorting)和局部排序(partial sorting)。在可以达到使用目的的情况下,优先使用后者,因为其效能更高。但由于一些关联式容器(set,map)和无序容器等不提供random-access iterator,所以不适用于这些排序算法。

但值得注意的是,对全体元素进行一次性排序通常比”始终维护它们保持排序状态“效率要高,所以具体使用何种容器还要看你所需要的是什么。

排序算法头文件

#include<algorithm>

1.完全排序

void
sort(random_access_iterator_beg,random_access_iterator_end)
void
sort(random_access_iterator_beg,random_access_iterator_end,binary_predicate op)
void
stable_sort(random_access_iterator_beg,random_access_iterator_end)
void
stable_sort(random_access_iterator_beg,random_access_iterator_end,binary_predicate op)
  • 在这里有sort()和stable_sort(),它们默认的第一形式都是用operator < 对区间[beg,end)内的所有元素排序。
  • sort()和stable_sort()的第二形式使用binary predicate作为排序准则,也就是使用者自己去定义的排序准则。
  • 注意,op必须针对元素值定义出strict weak ordering,也就是本文开篇所介绍的内容。
  • sort()与stable_sort()的区别在于,后者更加稳定,保证相等的元素的相对次序在排序后不发生改变。

时间复杂度:

sort():平均复杂度nlogn,最坏n^2。

stable_sort():若内存足够,则就是nlogn,不会变化。若没有足够内存,则复杂度是2nlogn。

比较常用的sort结构体排序

#include<iostream>
#include<algorithm>
using namespace std;
struct node
{
    int num1,num2;
}arr[10000];
bool cmp(node a,node b)//自定义比较准则
{
    return a.num1<b.num1;//以num1较小者优先排列
}
int main()
{
    arr[0]={1,2};
    arr[1]={2,1};
    arr[2]={3,4};
    arr[3]={4,3};
    sort(arr,arr+4,cmp);//严格按照要求传入参数
    for(int i=0;i<4;++i)
    {
        cout<<arr[i].num1<<" ";
    }
    cout<<endl;
    for(int i=0;i<4;++i)
    {
        cout<<arr[i].num2<<" ";
    }
return 0; }

 

2.局部排序

void
partial_sort(random_access_iterator_beg,random_access_iterator_sortend,random_access_iterator_end)
void
partial_sort(random_access_iterator_beg,random_access_iterator_sortend,random_access_iterator_end,binary_predicate op)

 

  • 第一形式以operator < 对[beg,end)区间内元素进行排序,使[beg,sortend)区间内元素处于有序状态。
  • 第二形式使用binary predicate作为排序准则,也就是使用者自己去定义的排序准则。
  • 除了与sort所需要注意的相同外,partial_sort()并不对全部元素排序,你传入的参数分别是排序首部,排序尾部,整体区间尾部。它会按照你所指示的区间进行排序,不用进行多余的操作。
  • 如果sortend等于end的话,那么partial_sort()会对整个序列排序,平均而言其性能不及sort(),但最差情况则优于sort()。

时间复杂度:在线性与nlogn之间。

3.根据第n个元素排序

void
nth_element(random_access_iterator_beg,random_access_iterator_nth,random_access_iterator_end)
void
nth_element(random_access_iterator_beg,random_access_iterator_nth,random_access_iterator_end,binary_predicate op)

 

两种形式都对[beg,end)区间内的元素排序,使第n个位置上的元素就位,也就是说,在位置n之前的元素都小于等于它,所有之后的元素都大于等于它。这样,你就得到了”根据n位置上的元素“分割开来的两个子序列,第一子序列的元素统统小于第二子序列的元素,但是处于无序状态。同样的,该算法也提供自定义排序准则。

时间复杂度:平均为线性。

nth_element操作举例

#include<iostream>
#include<algorithm>
bool cmp(int a,int b)
{
    return a>b;
}
using namespace std;
int main()
{
    int a[]={1,5,6,2,9,7,3,4,10,8};
    int elem=a[2];
    nth_element(a, a+3, a+10);//第一种形式,默认为<
    int i=0;
    while(a[i]<elem)
    {
        cout<<a[i]<<" ";
        i++;
    }
    cout<<endl;
    int b[]={1,5,6,2,9,7,3,4,10,8};
    nth_element(b,b+3,b+10,cmp);//传入重载函数
    int j=0;
    while(b[j]>elem)
    {
        cout<<b[j]<<" ";
        j++;
    }
}

 运行结果

由此可见虽然分割出了序列,但顺序是打乱的。

 

 

 

猜你喜欢

转载自www.cnblogs.com/cloudplankroader/p/10434931.html