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

关联容器 通过键(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. static在C中有了第二种含义:用来表示不能被其它文件访问的全局变量和函数

    C++变量根据定义位置的不同,具有不同的作用域,作用域可分为6种:全局作用域,局部作用域,语句作用域,类作用域,命名作用域和文件作用域. 从作用域看: 全局变量具有全局作用域.全局变量只需在一个源文件 ...

  2. 【转载】CentOS6.5_X64下安装配置MongoDB数据库

    [转载]CentOS6.5_X64下安装配置MongoDB数据库 2014-05-16 10:07:09|  分类: 默认分类|举报|字号 订阅      下载LOFTER客户端 本文转载自zhm&l ...

  3. 微信内置浏览器的JS API

    /**! * 微信内置浏览器的Javascript API,功能包括: * * 1.分享到微信朋友圈 * 2.分享给微信好友 * 3.分享到腾讯微博 * 4.新的分享接口,包含朋友圈.好友.微博的分享 ...

  4. kvm虚拟机--存储池配置梳理(转)

    1.创建基于文件夹的存储池(目录) 2.定义存储池与其目录 1 # virsh pool-define-as vmdisk --type dir --target /data/vmfs 3.创建已定义 ...

  5. ng2-timesheet, 一个timesheet.js的angular2复制版

    一个 timesheet.js (JavaScript library for HTML5 & CSS3 time sheets) 的 Angular 2 复制版 用法: npm instal ...

  6. DOM扩展札记

    Selector API HTML5 DOM扩展 Element Traversal规范 Selector API 众多JavaScript库中,最常用的一个功能就是根据css选择符选择与某个模式匹配 ...

  7. 【读书笔记】Programming Entity Framework CodeFirst -- 初步认识

    以下是书<Programming Entity Framework Code First>的学习整理,主要是一个整体梳理. 一.模型属性映射约定 1.通过 System.Component ...

  8. ngModel 值不更新/显示

    angular中的$scope是页面(view)和数据(model)之间的桥梁,它链接了页面元素和model,也是angular双向绑定机制的核心. 而ngModel是angular用来处理表单(fo ...

  9. C#性能优化之Lazy<T> 实现延迟初始化

    在.NET4.0中,可以使用Lazy<T> 来实现对象的延迟初始化,从而优化系统的性能.延迟初始化就是将对象的初始化延迟到第一次使用该对象时.延迟初始化是我们在写程序时经常会遇到的情形,例 ...

  10. C#开源磁盘/内存缓存引擎

    前言 昨天写了个 <基于STSdb和fastJson的磁盘/内存缓存>,大家可以先看看.下午用到业务系统时候,觉得可以改进一下,昨晚想了一个晚上,刚才重新实现一下. 更新 1. 增加了对批 ...