青山相待

            白云相爱

            梦不到紫罗袍共黄金带

            一茅斋

            野花开

            管甚谁家兴废谁成败

            陋巷单瓢亦乐哉

            贫,气不改!

            达,志不改!

【STL学习】map&set

技术不只是我的工作,也是我的生活,以后的博客中会穿插一些个人的喜悦、愤怒或者感悟,希望大家能够接受。

我所有的一切,比我技术更好的怕是我的脸皮了,昨天收到京东面试没有通过的消息,喊了几句“我好悲伤啊”就又能够继续我的生活了。呵呵,我不喜欢批判,但总是能看到自己的不足,好吧,这是一个痛并快乐的过程,我要造作的喊“悲伤”,我想放纵让亲友安慰我,我也要悄悄的学习,只为证明:我也很强,以后会更强。

在京东面试之后,对程序有了一点感触:数据结构和算法之间,一个程序员首先要考虑最合适的数据模型,之后才是算法,数据模型决定了存取的规模或者复杂度,比如10亿个URL,判断某一个URL是否在其中,我们可以设计一个比较长的字符串,通过 hash算法将每一个URL映射至字符串的5个位置,如果5个位置均为1,就代表了URL存在其中;又比如经典的火车进站出站问题,如果能想到栈和队列的模型就很容易解决。

map的特性、用途&用法

map称作映射或者关联数组,可以用来取代程序中一些很令人讨厌且低效率的线性匹配,提高效率和可读性。

map是一种(关键码,值)对偶的表,还很对基于关键码去查询做了特殊的优化。map的使用可以理解成一种下表不必是整数值的数组。

map和传统的关联数组,每个关键码相关联有唯一的一个值,,multimap允许元素中出现重复关键码,set和multiset可以看做是退化的关联数组,其中没有与关键码关联的值。

map提供双向迭代器,并要求其关键码类型提供一个小于操作以保持元素的有序性;对于那些没有明显顺序的元素,或者不必保持容器有序的情况,我们可以考虑用hash_map。

map中关键码是对偶的第一个元素,映射值是第二个;对任何pair,我们总是用first和second索引其第一个和第二个元素;pair的用途也不仅限于map的实现,pair本身也是一个标准库类,pair可以用make_pair快速创建。

map的特征性操作:采用下表运算法提供的关联查找。 

  map的下标操作和find该用哪个?

map的下标运算符[]将关键码作为下标去执行查找,如果关键码不存在,则插入一个具有该关键码和mapped_type类型默认值的元素至map中,因此下标运算符[]在map应用中需要慎用,const_map不能用,只希望确定某一个关键值是否存在而不希望插入元素时也不应该使用,mapped_type类型没有默认值也不应该使用。如果find能解决需要,尽可能用find。

map插入和删除元素:

map最方便的插入元素方式是下标操作;map也可以通过insert插入元素和erase删除元素,clear清除所有元素。insert和erase与其他STL容器不同,没有迭代器参数,返回值也是一个pair。erase的返回值是成功删除的元素个数,通过这个值我们可以判断要删除的关键码是否存在map中。

multimap

multimap支持重复关键码的数据,因此不支持下标操作;multimap的insert操作总是成功的并返回迭代器,equal_range、lower_bound、upper_bound是用关键码访问多重元素的基本手段。

set

一个set也可以看做一个map,其中的值是无关紧要的,只保留了关键码;set依靠的是比较操作(默认为<)而不是相等(==),这隐含着元素的相等需要由不相等定义,而且迭代通过set是有序的;不支持下标操作。

multiset

一种允许重复关键码的set ,通过equal_range、lower_bound、upper_bound操作访问重复关键码。

  关于map的后台实现

map后台基于红黑树,一种非典型的平衡二叉树。

  小结

map和set是STL中很有用的数据结构,应用非常广泛,STL的容器应用非常广泛,甚至可以这么说:学会了所有的STL用法和特性以后,除非必要很少会用到基本的数组和链表。 

补充 

用multimap实现了一个电话簿程序,包括插入、查找、删除,允许同一个联系人拥有多个联系方式:  

 

 

#include<iostream>
#include<map>
#include<string>
using namespace std;
multimap<string, string> book;
int main()
{
string name, num, op;
multimap<string, string>::iterator itorlower;
multimap<string, string>::iterator itorupper;
cout << "telephone book DEMO" << endl;
while (1)
{
name.clear();
num.clear();
op.clear();
cout << "input your select" << endl;
cout << "1.Add new linkman" << endl;
cout << "2.query linkman" << endl;
cout << "3.delete linkman" << endl;
cout << "4.quit" << endl;
cin >> op;
if (!op.compare("1"))
{
cin >> name;
cin >> num;
if ((itorlower = book.lower_bound(name)) != book.end())
{
itorupper = book.upper_bound(name);
for (;itorlower != itorupper; itorlower++)
{
if (!itorlower->second.compare(num))
{
cout << "linkman and telephone num already exist" << endl;
break;
}
}
if (itorlower == itorupper)
book.insert(make_pair(name, num));
}
else
{
book.insert(make_pair(name, num));
}
}
else if (!op.compare("2"))
{
cin >> name;
if ((itorlower = book.lower_bound(name)) != book.end())
{
itorupper = book.upper_bound(name);
for (;itorlower != itorupper; itorlower++)
{
cout << "linkman " << itorlower->first << " num " << itorlower->second << endl;
}
}
}
else if (!op.compare("3"))
{
cin >> name;
while ((itorlower = book.lower_bound(name)) != book.end())
{
book.erase(itorlower);
}
}
else if (!op.compare("4"))
{
break;
}
else
{
cout << "input error, try again" << endl;
}
}
return 0;
}
posted @ 2014-06-27 10:25  Leo.Z  阅读(284)  评论(0编辑  收藏  举报