深入探讨关联容器的“等价”机制

C++ STL中常用的关联容器有std::set、std::map等,这些关联容器具有容器内部元素自动排序的能力。

需要了解的是,在容器内部,对元素进行排序根据的是“等价”关系而不是“相等”关系,更确切的说,是元素所属类型的“<”运算符而不是“==”运算符决定了容器内部的排序行为。

以set为例,当以下表达式返回为true的时候,容器将两个元素v1、v2判定为等价关系,此时若set中已有v1,则v2将不能再被添加到容器里:

!(v1<v2) && !(v2<v1)    //表达式1

这样一来,对关联容器而言,有两个点需要注意:

1.定义一个关联容器变量,需要保证其元素的类型定义了<操作符,否则便会编译报错。有两种定义<操作的方式:

1) 首先,可以在类的内部定义operator<操作符。

2) 或者,另外定义一个比较类,内含一个定义了元素类型比较行为的函数。如下代码所示:

class AType  //元素类型
{
public:
	int data;
	AType(int d){data=d;}
};

struct DereferenceLess   //比较类
{
	bool operator()(AType t1,AType t2)const
	{
		return t1.data<t2.data;
	}
};

int main()
{
	std::set<AType,DereferenceLess> sets;
	sets.insert(AType(5));
	sets.insert(AType(2));
	return 0;
}

2.为容器定义的"<"操作符不得出现以下情况:当两个元素事实上“相等”时,运用前面所描述的表达式1得到的结果却是“等价”的。

举个例子,假设我们定义<=为set的<操作符,那么可以这么样写:

sed::set<int,less_equal<int>> s;

 我们首先插入一个元素10,然后在插入一个元素10:

s.insert(10)
s.insert(10)

 运用表达式1,我们可以得到false。说明这前后两个10之间是不等价的,因此s中就会有两个10元素,这是严重违反set定义的。

因此,你需要记住,比较函数的返回值表明的是按照该函数定义的排列顺序,一个值是否在另一个值之前。相等的值从来不会有前后顺序关系,所以,对于相等的值,比较函数应当始终返回false。

时间: 2024-10-12 03:47:30

深入探讨关联容器的“等价”机制的相关文章

关联容器(底层机制) — hashtable

C++ 11已将哈希表纳入了标准之列.hashtable是hash_set.hash_map.hash_multiset.hash_multimap的底层机制,即这四种容器中都包含一个hashtable. 解决碰撞问题的办法有许多,线性探测.二次探测.开链等等.SGI STL的hashtable采用的开链方法,每个hash table中的元素用vector承载,每个元素称为桶(bucket),一个桶指向一个存储了实际元素的链表(list),链表节点(node)结构如下: template <cl

关联容器(底层机制) — 红黑树

set.map.multiset.multimap四种关联式容器的内部都是由红黑树实现的.在STL中红黑树是一个不给外界使用的独立容器.既然是容器,那么就会分配内存空间(节点),内部也会存在迭代器.关于红黑树的一些性质,可以参考"数据结构"中的笔记,这里只记录STL中的红黑树是如何实现的. 和slist一样,红黑树的节点和迭代器均采用了双层结构: 节点:__rb_tree_node继承自__rb_tree_node_base 迭代器:__rb_tree_iterator继承自__rb_

STL源码剖析---关联容器

标准关联容器分为set和map两大类,包括multiset和multimap,这些容器的底层机制都是RB-tree.标准之外的关联容器有hashtable 以及以此hash table为底层机制而完成的hash_set(散列集合) hash_map(散列映射表) hash_multiset  hash_multimap. 序列和关联容器各自的内部关系是内含的,例如heap内含一个vector,priority_quehe内含一个heap,stack和queue都内含一个deque,set/map

[C++]高效使用关联容器的一些建议

关联容器 本文介绍在关联容器中常见的一些的问题以及提升使用关联容器的建议. 1. 理解相等(equality)和等价(equivalence)的区别. 相等是以operator==为基础的.等价是以operator<为基础的. 例如find的定义是相等,他用operator==来判断,这是比较容易理解的. 而等价关系是以"在已排序的区间中对象值的相对顺序"为基础的.也就是说,如果两个值中任何一个(按照既定的排列顺序)都在另一个的前面,那么他们就是等价的. !(w1 < w2

第11章 关联容器

map,管理数组,存储“关键字-值” set,简单集合,存储“关键字” 四个关联容器的头文件map.set.unordered_map.unordered_set 关联容器有8种,特点如下: 每个容器都是set或者map 分为允许关键字重复(multi)和不允许关键字重复 顺序保存和无序保存(unordered,哈希函数组织的结构) unordered_multiset是一个允许关键字重复,元素无序保存的集合 set是一个要求关键字不重复,元素有序保存的集合 map<string, size_t

C++拾遗(七)——关联容器

关联容器(Associative containers)支持通过键来高效地查找和读取元素.两个基本的关联容器类型是 map 和set.map 的元素以键-值(key-value)对的形式组织:键用作元素在 map 中的索引,而值则表示所存储和读取的数据.set仅包含一个键,并有效地支持关于某个键是否存在的查询.set 和 map 类型的对象所包含的元素都具有不同的键,不允许为同一个键添加第二个元素.如果一个键必须对应多个实例,则需使用 multimap 或 multiset,这两种类型允许多个元

Effective STL --关联容器

高效STL-关联容器 标准关联容器中最重要的就是基于等价而不是相等.比如对于基本的函数库有find函数,但是对于set关联容器也是有find成员函数的.因为标准关联容器保持有序,所以每一个容器必须有一个定义了怎么保持东西有序的比较函数(默认是less).等价是根据这个比较函数定义的,所以标准关联容器的用户只需要为他们要使用的任意容器指定一个比较函数 必须为指针的关联容器指定比较类型 一定要明确对于一个容器来说,容器内的迭代器是存入该容器对象的指针,比如一个关联容器存入指针类型,那么使用这个容器的

关联容器 — hash_set

容器hash_set是以hash table为底层机制的,几乎所有的操作都是转调用hash table提供的接口.由于插入无法存储相同的键值,所以hash_set的插入操作全部都使用hash table的insert_unique接口,代码如下: pair<iterator, bool> insert(const value_type& obj) { pair<typename ht::iterator, bool> p = rep.insert_unique(obj);

关联容器 — hash_map

hash_map和map的用法很相似,只是底层机制有所不同. hash_map容器采用的底层机制是hash table代码: template <class Key, class T, class HashFcn = hash<Key>, class EqualKey = equal_to<Key>, class Alloc = alloc> class hash_map { private: typedef hashtable<pair<const Key