stl容器排序

亦凉 2022-08-05 00:50 275阅读 0赞

C++编程优与Pascal的原因之一是C++中存在STL(标准模板库)。STL存在很多有用的方法。

C++模板库中的许多方法都需要相关参数有序,例如Sort()。显然,如果你想对一个集合进行排序,你必须要知道集合中的对象,那个在前那个在后。因此,学会如何定义比较方法是非常重要的。

C++模板库的许多容器需要相关类型有序,例如set 和priority_queue

这篇文章旨在告诉大家如何为一个类定义一个排序方法,以便在STL容器或者方法中使用。 作为一个C++程序员,你应该知道这些方法。

如何定义排序?

简而言之,为一个类定义排序,我们就可以知道类的任意两个对象在排序的过程中谁在前谁在后。我们可以用一个方法来实现,这个方法返回一个bool值表示谁排在前面。显然,我们希望实现一个类似,f(x,y),这种形式的方法。它接收同一类型的对象作为两个参数,返回值则表明谁会出现在谁前面。

严格弱序化

几乎所有的方法或容器都需要排序来满足数学意义上的标准严格弱序化,否则这些方法或容器的行为将不可预知。

假设f(x,y)是一个比较函数。 如果该函数满足如下条件则它是严格弱序化的。

1.f(x,x) = false;

  1. if f(x,y) then !f(y,x)

3.if f(x,y) and f(y,z) then f(x,z)

  1. if !f(x,y)&&!f(y,x) then x==y; if x==y and y==z then x==z;

看上去有点晕乎,不过不用担心,只要你的比较方法能够满足对相等元素永远返回false,那你的方法就满足要求了。

三种实现方式:

  1. 定义 < 操作符。

    使用这种方法可以使我们自定义的类能够获得与生俱来的排序能力。例如,如果有如下类:

?










1


2


3


4



struct
Edge


{


int
from,to ,weight;


};

因为要实现Kruskai算法,你希望图中的所有边依据权重按降序排列。 像这样来定义 operator<:

?










1


2


3


4


5


6


7


8



struct
Edge


{


        
int
from,to ,weight;


        
bool
operator <(Edge other)
const


        
{


                
return
weight>other.weight;


        
}      


};   

你定义的方法必须按照如下方法声明:

  1. bool operator< (T other) const

注意: const关键字是必须的。

如果你不喜欢这种方式,比如,明明是要比较两个对象,方法却只有一个参数。你可以选择如下方式:

?










1


2


3


4


5


6


7


8



struct
Edge


{


  
int
from,to weight;


  
friend
bool
operator<(Edge a,Edge b)


  {


    
return
a.weight>b.weight;


  }


};

STL的pair就具有与生俱来的排序能力。两个pair对象的比较这样的:先比较第一个参数,如果第一个参数相同再比较第二个参数。

所有内置类型都具有与生俱来的排序能力,这是由编译器赋予的。

  1. 自定义排序方法。

使用这种方式常常用在如下情形:

a.比较内置类型

b.不能修改需要比较的类型

c.除了类型自定义的比较方式以外的比较方法

简单来说,一个比较方法接收两个同类型的对象作为参数并且返回一个bool值,原型如下:

?










1



bool
name(T a,T b);

  1. 重载()操作符

我们可以将比较函数作为STL容器构造函数的第一个参数,并且把函数类型作为模板参数。例如:

?










1



set<
int
,
bool
(*)(
int
,
int
)> s(cmp);

这样做或多或少会让人费解。那我们就来看看如何使用仿函数来消除你的疑惑吧。

我们需要定义一个新的类并重载()操作符。

  1. vector<int> occurrences;
  2. struct cmp
  3. {
  4. bool operator()(int a, int b)
  5. {
  6. return occurrences[a] < occurrences[b];
  7. }
  8. };

现在我们就可以把这个类作为模板参数传递给STL容器了。

?










1


2


3



set<
int
, cmp> s;


 


priority_queue<
int
, vector<
int
>, cmp> pq;

STL也有一些内置的仿函数,例如less,greater等。

仿函数可以通过初始化然后像普通函数一样使用。最简单的就是在仿函数后面加上()。

?










1



sort(data.begin(), data.end(), greater<
int
>());

发表评论

表情:
评论列表 (有 0 条评论,275人围观)

还没有评论,来说两句吧...

相关阅读

    相关 STL 容器类型

    1. STL有6种序列容器类型  1 vector     向量 相当于一个数组     在内存中分配一块连续的内存空间进行存储。支持不指定vector大小

    相关 stl容器排序

    C++编程优与Pascal的原因之一是C++中存在STL(标准模板库)。STL存在很多有用的方法。 C++模板库中的许多方法都需要相关参数有序,例如Sort()。显然,如果你

    相关 STL 容器小结

    顺序容器:为程序员提供了控制元素存储和访问顺序的能力。这种顺序不依赖于元素的值,而是与元素加入容器是的位置相对应。 顺序容器几乎可以保存任意类型的元素。Eg: vector<

    相关 c++ 容器STL

    STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的