原文地址:http://fusharblog.com/3-ways-to-define-comparison-functions-in-cpp/

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

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

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

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

如何定义排序?

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

严格弱序化

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

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

1.f(x,x) = false;

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

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

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

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

三种实现方式:

1. 定义 < 操作符。

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

struct Edge
{
int from,to ,weight;
};

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

struct Edge
{
int from,to ,weight;
bool operator <(Edge other) const
{
return weight>other.weight;
}
};

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

bool operator< (T other) const

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

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

struct Edge
{
  int from,to weight;
  friend bool operator<(Edge a,Edge b)
  {
    return a.weight>b.weight;
  }
};

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

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

2. 自定义排序方法。

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

a.比较内置类型

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

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

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

bool name(T a,T b);

3. 重载()操作符

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

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

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

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

vector<int> occurrences;
struct cmp
{
bool operator()(int a, int b)
{
return occurrences[a] < occurrences[b];
}
};

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

set<int, cmp> s; 

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

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

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

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

C++中定义比较函数的三种方法的更多相关文章

  1. [转]Javascript定义类的三种方法

    作者: 阮一峰 原文地址:http://www.ruanyifeng.com/blog/2012/07/three_ways_to_define_a_javascript_class.html 将近2 ...

  2. Android中全屏 取消标题栏,TabHost中设置NoTitleBar的三种方法(转)

    Android中全屏 取消标题栏,TabHost中设置NoTitleBar的三种方法http://www.cnblogs.com/zdz8207/archive/2013/02/27/android- ...

  3. Openerp 中打开 URL 的三种 方法

    来自:http://shine-it.net/index.php/topic,8013.0.html 最近总结了,Openerp 中打开 URL 的三种 方法: 一.在form view 添加 < ...

  4. mysql 中添加索引的三种方法

    原文:http://www.andyqian.com/2016/04/06/database/mysqleindex/ 在mysql中有多种索引,有普通索引,全文索引,唯一索引,多列索引,小伙伴们可以 ...

  5. jQuery中detach&&remove&&empty三种方法的区别

    jQuery中empty&&remove&&detach三种方法的区别 empty():移除指定元素内部的所有内容,但不包括它本身 remove():移除指定元素内部的 ...

  6. vue后台管理项目中菜单栏切换的三种方法

    第一种方法:vue嵌套路由(二) <el-menu :default-active="defaultActive" style="min-height: 100%; ...

  7. STM32中AD采样的三种方法分析

    在进行STM32F中AD采样的学习中,我们知道AD采样的方法有多种,按照逻辑程序处理有三种方式,一种是查询模式,一种是中断处理模式,一种是DMA模式.三种方法按照处理复杂方法DMA模式处理模式效率最高 ...

  8. mfc 在VC的两个对话框类中传递参数的三种方法

    弄了好久,今天终于把在VC中的对话框类之间传递参数的问题解决了,很开心,记录如下: 1. 我所建立的工程是一个基于MFC对话框的应用程序,一共有三个对话框,第一个对话框为主对话框,所对应的类为CTMD ...

  9. cocos2dx中创建动画的三种方法

    1.最最原始的方法,先创建动画帧,再创建动画打包(animation),再创建动画(animate) 第一步: 创建动画帧:CCSpriteFrame,依赖于原始的资源图片(xx.png,xx.jpg ...

随机推荐

  1. C#中string[ ] args是什么意思,又有什么用呢

    转载:http://blog.sina.com.cn/s/blog_8b7263d1010172jv.html C#控制台程序中static void Main(string[ ] args) str ...

  2. encodeURIComponent编码后java后台的解码

    解决方法一: JavaScript: window.self.location="searchbytext.action?searchtext="+encodeURICompone ...

  3. phpcms v9 源码解析-1 index.php

    这个是phpcms V9 的入口文件index.php. V9程序的执行绝大多数是从这个文件开始的,但不绝对,在项目下面的api.php和plugin.php是另外的入口文件,这里我们先不做深究. 在 ...

  4. MYSQL查询某字段中以逗号分隔的字符串的方法

    首先我们建立一张带有逗号分隔的字符串. CREATE TABLE test(id int(6) NOT NULL AUTO_INCREMENT,PRIMARY KEY (id),pname VARCH ...

  5. Dll学习三_Dll 相互间以及主程序间的数据共享——测试未通过,应该用内存映射

    测试环境:XP,DELPHI XE 验证通过结构:主程序+一个Dll窗体 共享方式原理:通过主程序与各Dll定义相同的参数结构体,由主程序实例化该结构体,对于各Dll间的共享,通过传主程序实例化的结构 ...

  6. PHP搜索MYSQL数据库加分页浏览小结

    PHP搜索加分页浏览小结: 1 分页后再做搜索 2 这里对于url的拼接,以及模糊查询,搜索时候的显示添加,SQL语句的拼接 3 对于页面传递过来的超级链接的变量,如果不存在就要设置,对于可能抛出异常 ...

  7. sliding windows (poj 2823) 题解

    [问题描述] 给你一个长度为N的数组,一个长为K的滑动的窗体从最左移至最右端,你只能见到窗口的K个数,每次窗体向右移动一位,如下表: [样例输入] 8 3 1 3 -1 -3 5 3 6 7 [样例输 ...

  8. JqueryUI

    http://jqueryui.com/ http://www.runoob.com/jqueryui/jqueryui-tutorial.html

  9. JS中的集中页面跳转的方法

    第一种:    <script language="javascript" type="text/javascript">           wi ...

  10. RAC本地数据文件迁移至ASM的方法--非归档模式

    系统环境:rhel6.2_x64+Oracle RAC11g 操作过程: 1.非归档模式 SQL> archive log list; Database log mode No Archive ...