关联容器 和 顺序容器 的本质差别在于:

关联容器 通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。

Goto: C++ Primer 第十章 关联容器

关联式容器依据特定的排序准则,自动为其元素排序。排序准则以函数形式呈现,用来比较元素值(value)或元素键(key)。缺省情况下以operator<进行 比较,不过你也可以提供自己的比较函数,定义出不同的排序准则。

通常关联式容器 由二叉树(binary tree)实现。在二叉树中,每个元素(节 点)都有一个父节点和两个子节点;左子树的所有元素都比自己小,右子树的所有元素都比自己大。关联式容器的差别主要在于元素的类型以及处理重复元素时的方式。

STL预先定义好的关联式容器有:

  • 集合(set),大小可变的集合,支持通过键实现的快速读取
  • 多重集合(multiset),支持同一个键多次出现的 map 类型
  • 映射(map),关联数组:元素通过键来存储和读取
  • 多重映射(multimap),支持同一个键多次出现的 set 类型

映射(map)

一、基本操作

int main()
{
cout << "Hello World!" << endl;

// 初始化方法1
pair<string, int> author1;
author1.first = "lolo";
author1.second = ;
// 初始化方法2
pair<string, int> author2;
author2 = make_pair("lolo", ); map<string, int> myMap; // 初始化方法一
myMap["jeff"] = ; // 初始化方法二
myMap.insert(make_pair("Bing", 99));
cout << myMap["jeff"] << endl;
cout << myMap["lolo"] << endl; //Actually, new element added. return ;
}
 

隐患:"被搜索的" 空键值

查找Key不存在的内容,会默认自动添加。

(1) The map contains this key. So it will return the corresponding key value.

(2) The map doesn't contain the key. In this case, it will automatically add a key to the map with null value.

方案:键值存在么?

  • 查找键值

找到第一个就返回了。

if ( m.find("f") == m.end() ) {
// not found
} else {
// found
}
  • 计数键值

需要整个遍历一遍。

if (m.count("f") > )
cout << " is an element of m.\n";
else
cout << " is not an element of m.\n";

二、key 排序

默认排序

原理类似 Max/Min heap 默认是key排序.自定义排序,则在模板中添加了第三项.自动一

#include<map>
#include<string>
#include<iostream>
using namespace std; typedef pair<string, int> PAIR; ostream& operator<<(ostream& out, const PAIR& p) {
return out << p.first << "\t" << p.second;
} int main() {
map<string, int, greater<string>> name_score_map;
name_score_map["LiMin"] = ;
name_score_map["ZiLinMi"] = ;
name_score_map["BoB"] = ;
name_score_map.insert(make_pair("Bing",));
name_score_map.insert(make_pair("Albert",));

for (map<string, int>::iterator iter = name_score_map.begin(); iter != name_score_map.end(); ++iter) {
cout << *iter << endl;
}
return ;
}

自定义排序

这里使用了类函数,虽然是结构体,但其实区别不大.

struct CmpByKeyLength {
bool operator()(const string& k1, const string& k2) {
return k1.length() < k2.length();
}
}; // 使用了函数类,效率更高

int main() {
map<string, int, CmpByKeyLength> name_score_map;
name_score_map["LiMin"] = ;
name_score_map["ZiLinMi"] = ;
name_score_map["BoB"] = ;
name_score_map.insert(make_pair("Bing",));
name_score_map.insert(make_pair("Albert",));
for (map<string, int>::iterator iter = name_score_map.begin(); iter != name_score_map.end(); ++iter) {
cout << *iter << endl;
}
return ;
}

集合(set)

插入操作

注意insert后的返回值模板类型.插入后打印,本身的值是排序好的.类似于python中的 bisect模块.

void func_set(void)
{
std::set<int> myset;
std::set<int>::iterator it;
// 插入操作后的模板类型:(1) 插入值的指针,(2) 插入成功与否
std::pair<std::set<int>::iterator, bool> ret; // set some initial values:
for (int i=; i<=; ++i) {
myset.insert(i*); // set: 10 20 30 40 50
} // Jeff --> ret.second 插入成功? 原来没有;插入失败?原本就有。
ret = myset.insert(); if (ret.second==false) {
it=ret.first; // "it" now points to element 20
} myset.insert (it, ); // max efficiency inserting
myset.insert (it, ); // max efficiency inserting
myset.insert (it, ); // no max efficiency inserting int myints[]= {,,}; // 10 already in set, not inserted
myset.insert (myints, myints+); std::cout << "myset contains:";
for (it=myset.begin(); it!=myset.end(); ++it)
std::cout << ' ' << *it;
std::cout << '\n';
}

实现原理

c++之stl 二叉树

set由 "二叉搜索树" 实现,并且对树进行了平衡处理,使得元素在树中分部较为均匀,因此能保持搜索、插入、删除的复杂度在O(logn)。

 

multimap

何时有用?

一般不用,用时自己实现还比较麻烦,不得不用这个接口,毕竟自己不想去实现 "红黑树".

How is it useful: Multimaps are one of those things that you need rarely, but when you need them, you really need them.

/*
*
********************************************
* multimap多重映照容器的基础说明:
********************************************
*
* multimap多重映照容器:容器的数据结构采用红黑树进行管理
* multimap的所有元素都是pair:第一元素为键值(key),不能修改;第二元素为实值(value),可被修改
*
* multimap特性以及用法与map完全相同,唯一的差别在于:
* 允许重复键值的元素插入容器(使用了RB-Tree的insert_equal函数)
* 因此:
* 键值key与元素value的映照关系是多对多的关系
* 没有定义[]操作运算
*
* Sorted Associative Container Pair Associative Container Unique Associative Container
*
* 使用multimap必须使用宏语句#include <map>
*
**************************************************************************************
*
* 创建multimap对象:
* 1.multimap<char,int,greater<char> > a; //元素键值类型为char,映照数据类型为int,键值的比较函数对象为greater<char>
* 2.multimap(const key_compare& comp) //指定一个比较函数对象comp来创建map对象
* 3.multimap(const multisetr&); //multimap<int,char*> b(a); //此时使用默认的键值比较函数less<int>
* 4.multimap(first,last);
* 5.multimap(first,last,const key_compare& comp);
*
* //Example:
* pair<const int ,char> p1(1,'a');
* pair<const int ,char> p2(2,'b');
* pair<const int ,char> p3(3,'c');
* pair<const int ,char> p4(4,'d');
* pair<const int ,char> pairArray[]={p1,p2,p3,p4};
* multimap<const int,char> m4(pairArray,pairArray+5);
* multimap<const int,char> m3(m4);
* multimap<const int,char,greater<const int> > m5(pairArray,pairArray+5,greater<const int>());
*
**************************************************************************************
*
* 元素的插入
* //typedef pair<const key,T> value_type;
* pair<iterator,bool> insert(const value_type& v);
* iterator insert(iterator pos,const value_type& v);
* void insert(first,last);
*
**************************************************************************************
*
* 元素的删除
* void erase(iterator pos);
* size_type erase(const key_type& k); //删除等于键值k的元素
* void erase(first,last); //删除[first,last)区间的元素
* void clear();
*
**************************************************************************************
*
* 访问与搜索
*
* iterator begin();iterator end(); //企图通过迭代器改变元素是不被允许的
* reverse_iterator rbegin();reverse_iterator rend();
*
* iterator find(const key_type& k) const;
* pair<iterator,iterator> equal_range(const key_type& k) const;//返回的pair对象,
* //first为lower_bound(k);大于等于k的第一个元素位置
* //second为upper_bound();大于k的第一个元素位置
*
* 其它常用函数
* bool empty() const;
* size_type size() const;
* size_type count(const key_type& k) const; //返回键值等于k的元素个数
* void swap();
*
* iterator lower_bound();iterator upper_bound();pair<iterator,iterator> equal_range();//上界、下届、确定区间
*
*
*
********************************************
** cumirror ** tongjinooo@163.com ** **
********************************************
*
*/ #include <map>
#include <string>
#include <iostream> // 基本操作与set类型,牢记map中所有元素都是pair
// 对于自定义类,初学者会觉得比较函数如何构造很麻烦,这个可以参照前面的书写示例
// 但若设置键值为int或char类型,无须构造比较函数 struct student{
char* name;
int age;
char* city;
char* phone;
}; int main()
{
using namespace std; student s[]={
{"童进",,"武汉","XXX"},
{"老大",,"武汉","XXX"},
{"饺子",,"武汉","XXX"},
{"王老虎",,"武汉","XXX"},
{"周润发",,"武汉","XXX"},
{"周星星",,"武汉","XXX"}
};
pair<int,student> p1(,s[]);
pair<int,student> p2(,s[]);
pair<int,student> p3(,s[]);
pair<int,student> p4(,s[]); //键值key与p1相同
pair<int,student> p5(,s[]);
pair<int,student> p6(,s[]);
multimap<int, student> a;
a.insert(p1);
a.insert(p2);
a.insert(p3);
a.insert(p4);
a.insert(p5);
a.insert(p6); // 会有重复的key
typedef multimap<int, student>::iterator int_multimap;
pair<int_multimap,int_multimap> p = a.equal_range();
int_multimap i = a.find();
cout<<"班上key值为"<< i->first<<"的学生有:"<<a.count()<<"名,"<<" 他们是:"<<endl;
for(int_multimap k = p.first; k != p.second; k++)
{
cout<<k->second.name<<endl;
}
cout<<"删除重复键值的同学"<<endl;
a.erase(i);
cout<<"现在班上总人数为:"<<a.size()<<". 人员如下:"<<endl;
for(multimap<int,student>::iterator j=a.begin(); j != a.end(); j++)
{
cout<<"The name: "<<j->second.name<<" "<<"age: "<<j->second.age<<" "
<<"city: "<<j->second.city<<" "<<"phone: "<<j->second.phone<<endl;
} return ;
}

End.

[c++] Associative Containers的更多相关文章

  1. 关联式容器(associative containers)

    关联式容器(associative containers) 根据数据在容器中的排列特性,容器可分为序列式(sequence)和关联式(associative)两种. 标准的STL关联式容器分为set( ...

  2. Associative Containers

    Notes from C++ Primer Associative containers differ in fundamental respect from the sequential conta ...

  3. Understand the Qt containers(有对应表)

    Container classes are one of the cornerstones of object-oriented programming, invaluable tools that ...

  4. C++ std::set

    std::set template < class T, // set::key_type/value_type class Compare = less<T>, // set::k ...

  5. C++ std::multimap

    std::multimap template < class Key, // multimap::key_type class T, // multimap::mapped_type class ...

  6. C++ std::map

    std::map template < class Key, // map::key_type class T, // map::mapped_type class Compare = less ...

  7. C++ std::multiset

    std::multiset template < class T, // multiset::key_type/value_type class Compare = less<T>, ...

  8. C++ 关联容器

    <C++ Primer 4th>读书笔记 关联容器和顺序容器的本质差别在于:关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素. 关联容器(Ass ...

  9. [Code::Blocks] Install wxWidgets & openCV

    The open source, cross platform, free C++ IDE. Code::Blocks is a free C++ IDE built to meet the most ...

随机推荐

  1. Await, and UI, and deadlocks! Oh my!

    It’s been awesome seeing the level of interest developers have had for the Async CTP and how much us ...

  2. Android中的PopupWindow

    1.功能 PopupWindow这个类用来实现一个弹出框,可以使用任意布局的View作为其内容,这个弹出框是悬浮在当前activity之上的,可以设置显示位置. 2.需求 弹出软键盘,实现键盘功能从而 ...

  3. 读bootstrap2.3.2有感2

    排版: Bootstrap定义的全局 font-size 是 14px,line-height 是 20px.这些样式应用到了 <body> 和所有的段落上.另外,对 <p> ...

  4. PPC MPC85xx e500学习笔记

    powerpc的内存体系结构 E500内核中包含内存管理单元MMU,其包含两个查找表(TLB0 Transaction Lookside Buffer)和TLB1来实现虚拟地址和物理地址的转化,其中T ...

  5. cmd输出的日志里有中文乱码的解决办法

    在命令行使用adb logcat命令直接输出日志中文内容显示乱码,原因是中文系统中cmd命令行窗口默认的编码是GBK,而LogCat打印的日志是UTF-8编码,所以adb logcat命令输出的中文内 ...

  6. Linux磁盘管理

    本系列的博客来自于:http://www.92csz.com/study/linux/ 在此,感谢原作者提供的入门知识 这个系列的博客的目的在于将比较常用的liunx命令从作者的文章中摘录下来,供自己 ...

  7. 一、ASP.NET MVC 路由(一)--- ASP.NET WebForm路由模拟

    ASP.NET WebForm 应用,用户请求的是物理文件,其中包括静态页面和动态页面,在Url中的显示都是服务器中一个物理文件的相对路径.但是ASP.NET MVC就不同了,用户请求的是Contro ...

  8. MongoDB之TextSearch简介

    MongoDB之TextSearch简介  MongoDB支持对文本内容执行文本搜索操作,其提供了索引text index和查询操作$text来完成文本搜索功能.下面我们通过一个简单的例子来体验一下M ...

  9. CentOS7(mini) 急速部署ASP.NET应用

    从mono 2.8+的时候就开始关注linux运行.NET的一些消息 最近闲来无事,发现mono官方已经提供有编译好的源,极大便利了部署过程,不需要自己去编译mono了 用Nancy.Owin写了一个 ...

  10. .NET 的 WebSocket 开发包比较

    编者按 本文出现在第三方产品评论部分中.在这一部分的文章只提供给会员,不允许工具供应商用来以任何方式和形式来促销或宣传产品.请会员报告任何垃圾信息或广告. Web项目常常需要将数据尽可能快地推送给客户 ...