STL应用之set
之前在解决一道算法题的时候,应用到set,特意对这个stl的容器类做了一些了解。在我的印象中,set就是一个元素不重复的集合,而事实上也正是这样的。无论从MSDN还是任何其它地方,都会告诉我们set的元素不可以重复。反之,只要元素不重复,就可以顺利的放入到set中。看起来这实在是再清楚不过了,但是仔细想一想的话,就会发现,话说只要不重复的元素就可以被放入到一个set中,但是什么样的元素是不重复的元素呢?或者说,什么样的元素是互不相同的呢?对于内置数据类型,也就是传说中的primary data type,像int 、 double、unsigned,甚至string,这些元素的“相同”非常容易理解,那么对于自定义类型呢?什么样的数据是相同的呢?什么样的数据又是不同的呢?
在以前学习STL的时候,曾经学到过,如果要将自定义的类型放入到set中的话,就需要重载“<”符号,原因是set是一个有序的集合,集合会按照“<”比较的大小,默认按照从小到大的顺序排列。假设我现在设计如下类型:
class MyType
{
public:
int a, b, c;
}
这是,为了让MyType类型可以顺利的放进set中,我必须重载“<”,这时问题来了,要如何重载呢?这个类型有三个数据成员,我能不能要求按照a的大小排列,如果a相等的话就随便按照b或者c的大小排列呢?如果近实现按照a的大小排列的话,重载函数如下:
bool operator<(const MyType& myType) const
{
return a<myType.a;
}
看起来简单明了,但是事实真的是这样吗?如果我声明一个set,并在其中放入MyType(1,2,3)、MyType(1,2,4)我能成功吗?实验了一下,结果如下:

测试时用的代码是这样的:
#include<iostream>
#include<set>
using namespace std;
class MyType
{
public:
int a, b, c;
MyType(int a, int b, int c):a(a), b(b), c(c){}
bool operator<(const MyType& myType) const
{
return a<myType.a;
}
};
int main()
{
set<MyType> se;
MyType type1(1,2,3);
MyType type2(1,2,4);
se.insert(type1);
se.insert(type2);
cout<<"The set size:"<<se.size()<<endl;
cout<<"Elements in the set as follows:"<<endl;
for(set<MyType>::iterator it = se.begin(); it != se.end(); it++)
{
cout<<"("<<it->a<<", "<<it->b<<", "<<it->c<<") ";
}
cout<<endl;
return 0;
}
结果很明显,当我已经把MyType(1,2,3)放到set中之后,就不能把MyType(1,2,4)放进去了。但是为什么呢?这两个对象看起来确实不一样啊!STL在比较是否相同的时候不是要比较每一个数据成员的吗?从上述的例子中,看到的确实不是这样的,STL不会自动的做任何比较,它仅对你说明过的动作干一些指定的活儿。在重载“<”的时候,当只指定众多数据成员中的一部分的时候,如果这部分都相同的话,set就认为是同一个元素了。就如上述所示一样,重载的时候仅作了a的比较,而没有说明如果a相同的话,是否对剩下的元素进行比较。这样一来,set认为MyType(1,2,3)和MyType(1,2,4)是一样的。要让set正确的进行大小的比较,针对自定义类型,就必须说明所有的数据成员的比较情况。如上述的例子的“<”重载,应该这样写:
bool operator<(const MyType& myType) const
{
return a<myType.a?true:(b<myType.b?true:c<myType.c);
}
这样一来,就完全说明了每一个数据成员的比较关系,set就可以正常工作了。还是MyType(1,2,3)、MyType(1,2,4)两个元素,这回运行的结果如下:

运行代码为:
#include<iostream>
#include<set>
using namespace std;
class MyType
{
public:
int a, b, c;
MyType(int a, int b, int c):a(a), b(b), c(c){}
bool operator<(const MyType& myType) const
{
return a<myType.a?true:(b<myType.b?true:c<myType.c);
}
};
int main()
{
set<MyType> se;
MyType type1(1,2,3);
MyType type2(1,2,4);
se.insert(type1);
se.insert(type2);
cout<<"The set size:"<<se.size()<<endl;
cout<<"Elements in the set as follows:"<<endl;
for(set<MyType>::iterator it = se.begin(); it != se.end(); it++)
{
cout<<"("<<it->a<<", "<<it->b<<", "<<it->c<<") ";
}
cout<<endl;
return 0;
}
STL应用之set的更多相关文章
- 详细解说 STL 排序(Sort)
0 前言: STL,为什么你必须掌握 对于程序员来说,数据结构是必修的一门课.从查找到排序,从链表到二叉树,几乎所有的算法和原理都需要理解,理解不了也要死记硬背下来.幸运的是这些理论都已经比较成熟,算 ...
- STL标准模板库(简介)
标准模板库(STL,Standard Template Library)是C++标准库的重要组成部分,包含了诸多在计算机科学领域里所常见的基本数据结构和基本算法,为广大C++程序员提供了一个可扩展的应 ...
- STL的std::find和std::find_if
std::find是用来查找容器元素算法,但是它只能查找容器元素为基本数据类型,如果想要查找类类型,应该使用find_if. 小例子: #include "stdafx.h" #i ...
- STL: unordered_map 自定义键值使用
使用Windows下 RECT 类型做unordered_map 键值 1. Hash 函数 计算自定义类型的hash值. struct hash_RECT { size_t operator()(c ...
- C++ STL简述
前言 最近要找工作,免不得要有一番笔试,今年好像突然就都流行在线笔试了,真是搞的我一塌糊涂.有的公司呢,不支持Python,Java我也不会,C有些数据结构又有些复杂,所以是时候把STL再看一遍了-不 ...
- codevs 1285 二叉查找树STL基本用法
C++STL库的set就是一个二叉查找树,并且支持结构体. 在写结构体式的二叉查找树时,需要在结构体里面定义操作符 < ,因为需要比较. set经常会用到迭代器,这里说明一下迭代器:可以类似的把 ...
- STL bind1st bind2nd详解
STL bind1st bind2nd详解 先不要被吓到,其实这两个配接器很简单.首先,他们都在头文件<functional>中定义.其次,bind就是绑定的意思,而1st就代表fir ...
- STL sort 函数实现详解
作者:fengcc 原创作品 转载请注明出处 前几天阿里电话一面,被问到STL中sort函数的实现.以前没有仔细探究过,听人说是快速排序,于是回答说用快速排序实现的,但听电话另一端面试官的声音,感觉不 ...
- STL的使用
Vector:不定长数组 Vector是C++里的不定长数组,相比传统数组vector主要更灵活,便于节省空间,邻接表的实现等.而且它在STL中时间效率也很高效:几乎与数组不相上下. #include ...
- [C/C++] C/C++延伸学习系列之STL及Boost库概述
想要彻底搞懂C++是很难的,或许是不太现实的.但是不积硅步,无以至千里,所以抽时间来坚持学习一点,总结一点,多多锻炼几次,相信总有一天我们会变得"了解"C++. 1. C++标准库 ...
随机推荐
- Linux下删除相互依赖的包
今天遇到一个问题,使用RPM 卸载包的时候两个包相互依赖 包A 和包B 卸载A的时候提示需要先卸载B ,反之亦然 经过一番百度 可以在命令后面加参数--nodeps 例如 rpm -e php-jso ...
- 顺序查找 && 折半查找
顺序查找 算法描述 顺序比较即可. 平均查找长度 (n+1)/2, 其中n为表长 ...
- 如何在Linux上面安装GCC 4.1.2
安装步骤: 1.首先下载GCC 4.1.2的source code package: $ wget http://mirrors.ustc.edu.cn/gnu/gcc/gcc-4.1.2/gcc-4 ...
- Jquery 获取table当前行内容
$("a[name='checkOriginal']").click(function () { var parent = $(this).parent().parent().fi ...
- UILabel字体间距调整
思路: 写一个 UILbel的子类:在子类里面重新布置UILbel的字体间距: 如代码 .h #import <UIKit/UIKit.h> @interface AdjustableUI ...
- Tomcat环境的搭建(web基础学习笔记一)
一.下载和安装Tomcat服务器 下载Tomcat安装程序包:http://tomcat.apache.org/ 点击[Download]跳转到如下图所示的下载页面 二.点击左侧要下载的版本,选择To ...
- SQL之查询函数LOCATE、POSITION、INSTR、FIND_IN_SET、IN、LIKE
- 安装ubuntu后不能从ubuntu引导修复方法
sudo fdisk -l sudo -i mkdir /media/tempdir mount /dev/sda7 /media/tempdir grub-install --root-direct ...
- 关于DES加密中的 DESede/CBC/PKCS5Padding
今天看到一段3DES加密算法的代码,用的参数是DESede/CBC/PKCS5Padding,感觉比较陌生,于是学习了一下. 遇到的java代码如下: Cipher cipher=Cipher.get ...
- 〖Linux〗build sqlite3 for Arm
Version: sqlite-autoconf-3080100.tar.gz Download: https://www.sqlite.org/download.html 1. toolchains ...