红黑树实现——STL中的map

From: http://blog.csdn.net/zhongjiekangping/article/details/6934571


红黑树实现——STL中的map

[ 2009-07-24 13:55:31 | 作者: dklkt ]
字号: 大 | 中 | 小
[转载]STL中map实现技术
来源: http://blog.csdn.net/Fandywang_jlu/archive/2008/03/23/2208363.aspx

红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。它是在1972年由Rudolf Bayer发明的,他称之为"对称二叉B树",它现代的名字是在 Leo J. Guibas 和 Robert Sedgewick 于1978年写的一篇论文中获得的。它是复杂的,但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。

红黑树是一种很有意思的平衡检索树。它的统计性能要好于平衡二叉树(有些书籍根据作者姓名,Adelson-Velskii和Landis,将其称为 AVL-树),因此,红黑树在很多地方都有应用。在C++ STL中,很多部分(目前包括set, multiset, map, multimap)应用了红黑树的变体(SGI STL中的红黑树有一些变化,这些修改提供了更好的性能,以及对set操作的支持)。

背景和术语

红黑树是一种特定类型的二叉树,它是在计算机科学中用来组织数据比如数字的块的一种结构。所有数据块都存储在节点中。这些节点中的某一个节点总是担当启始位置的功能,它不是任何节点的儿子;我们称之为根节点或根。它有最多两个"儿子",都是它连接到的其他节点。所有这些儿子都可以有自己的儿子,以此类推。这样根节点就有了把它连接到在树中任何其他节点的路径。

如果一个节点没有儿子,我们称之为叶子节点,因为在直觉上它是在树的边缘上。子树是从特定节点可以延伸到的树的某一部分,其自身被当作一个树。在红黑树中,叶子被假定为 null 或空。

由于红黑树也是二叉查找树,它们当中每一个节点都的比较值都必须大于或等于在它的左子树中的所有节点,并且小于或等于在它的右子树中的所有节点。这确保红黑树运作时能够快速的在树中查找给定的值。

用途和好处

红黑树和AVL树一样都对插入时间、删除时间和查找时间提供了最好可能的最坏情况担保。这不只是使它们在时间敏感的应用如即时应用(real time application)中有价值,而且使它们有在提供最坏情况担保的其他数据结构中作为建造板块的价值;例如,在计算几何中使用的很多数据结构都可以基于红黑树。

红黑树在函数式编程中也特别有用,在这里它们是最常用的持久数据结构之一,它们用来构造关联数组和集合,在突变之后它们能保持为以前的版本。除了O(log n)的时间之外,红黑树的持久版本对每次插入或删除需要O(log n)的空间。

红黑树是 2-3-4树的一种等同。换句话说,对于每个 2-3-4 树,都存在至少一个数据元素是同样次序的红黑树。在 2-3-4 树上的插入和删除操作也等同于在红黑树中颜色翻转和旋转。这使得 2-3-4 树成为理解红黑树背后的逻辑的重要工具,这也是很多介绍算法的教科书在红黑树之前介绍 2-3-4 树的原因,尽管 2-3-4 树在实践中不经常使用。

属性

红黑树是每个节点都有颜色特性的二叉查找树,颜色的值是红色或黑色之一。除了二叉查找树带有的一般要求,我们对任何有效的红黑树加以如下增补要求:

1.节点是红色或黑色。

2.根是黑色。

3.所有叶子(外部节点)都是黑色。

4.每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)

5.从每个叶子到根的所有路径都包含相同数目的黑色节点。

这些约束强制了红黑树的关键属性: 从根到叶子的最长的可能路径不多于最短的可能路径的两倍长。结果是这个树大致上是平衡的。因为操作比如插入、删除和查找某个值都要求与树的高度成比例的最坏情况时间,这个在高度上的理论上限允许红黑树在最坏情况下都是高效的,而不同于普通的二叉查找树。

要知道为什么这些特性确保了这个结果,注意到属性4导致了路径不能有两个毗连的红色节点就足够了。最短的可能路径都是黑色节点,最长的可能路径有交替的红色和黑色节点。因为根据属性5所有最长的路径都有相同数目的黑色节点,这就表明了没有路径能多于任何其他路径的两倍长。

在很多树数据结构的表示中,一个节点有可能只有一个儿子,而叶子节点包含数据。用这种范例表示红黑树是可能的,但是这会改变一些属性并使算法复杂。为此,本文中我们使用 "nil 叶子" 或"空(null)叶子",如上图所示,它不包含数据而只充当树在此结束的指示。这些节点在绘图中经常被省略,导致了这些树好像同上述原则相矛盾,而实际上不是这样。与此有关的结论是所有节点都有两个儿子,尽管其中的一个或两个可能是空叶子。

操作

在红黑树上只读操作不需要对用于二叉查找树的操作做出修改,因为它也二叉查找树。但是,在插入和删除之后,红黑属性可能变得违规。恢复红黑属性需要少量(O(log n))的颜色变更(这在实践中是非常快速的)并且不超过三次树旋转(对于插入是两次)。这允许插入和删除保持为 O(log n) 次,但是它导致了非常复杂的操作。

STL中的另一个类hash map是通过使用hash表来构造map的
参考: http://baike.baidu.com/view/133754.htm

对于STL中的具体实现可以参考《STL 源码剖析》
208页 5.2 RB-tree(红黑树)
237页 5.4 map

=========================================================
[转载]STL map常用操作简介 
来源: http://www.cnblogs.com/TianFang/archive/2006/12/30/607859.html

1。目录 
map简介 
map的功能 
使用map 
在map中插入元素 
查找并获取map中的元素 
从map中删除元素 

2。map简介 

map是一类关联式容器。它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响。对于迭代器来说,可以修改实值,而不能修改key。 

3。map的功能 
自动建立Key - value的对应。key 和 value可以是任意你需要的类型。 
根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。 
快速插入Key - Value 记录。 
快速删除记录 
根据Key 修改value记录。 
遍历所有记录。 

4。使用map 

使用map得包含map类所在的头文件
#include <map> //注意,STL头文件没有扩展名.h 

map对象是模板类,需要关键字和存储对象两个模板参数:
std:map<int, string> personnel;
这样就定义了一个用int作为索引,并拥有相关联的指向string的指针. 

为了使用方便,可以对模板类进行一下类型定义, 

typedef map<int, CString> UDT_MAP_INT_CSTRING; 
UDT_MAP_INT_CSTRING enumMap; 

5。在map中插入元素 

改变map中的条目非常简单,因为map类已经对[]操作符进行了重载 

enumMap[1] = "One";
enumMap[2] = "Two";
..... 

这样非常直观,但存在一个性能的问题。插入2时,先在enumMap中查找主键为2的项,没发现,然后将一个新的对象插入enumMap,键是2,值是一个空字符串,插入完成后,将字符串赋为"Two"; 该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。我们可以用以下方法来避免开销: 

enumMap.insert(map<int, CString> :: value_type(2, "Two")) 

6。查找并获取map中的元素 

下标操作符给出了获得一个值的最简单方法: 

CString tmp = enumMap[2]; 

但是,只有当map中有这个键的实例时才对,否则会自动插入一个实例,值为初始化值。 

我们可以使用Find()和Count()方法来发现一个键是否存在。 

查找map中是否包含某个关键字条目用find()方法,传入的参数是要查找的key,在这里需要提到的是begin()和end()两个成员,分别代表map对象中第一个条目和最后一个条目,这两个数据的类型是iterator. 

int nFindKey = 2;            //要查找的Key
//定义一个条目变量(实际是指针)
UDT_MAP_INT_CSTRING::iterator it= enumMap.find(nFindKey); 
if(it == enumMap.end()) {
    //没找到
}
else {
    //找到


通过map对象的方法获取的iterator数据类型是一个std::pair对象,包括两个数据 iterator->first 和 iterator->second 分别代表关键字和存储的数据 

7。从map中删除元素 

移除某个map中某个条目用erase() 

该成员方法的定义如下 
iterator erase(iterator it); //通过一个条目对象删除 
iterator erase(iterator first, iterator last);        //删除一个范围 
size_type erase(const Key& key); //通过关键字删除 

clear()就相当于 enumMap.erase(enumMap.begin(), enumMap.end());

=========================================================
[转载]STL中map用法详解
来源: http://www.kuqin.com/cpluspluslib/20071231/3265.html

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的,后边我们会见识到有序的好处。

下面举例说明什么是一对一的数据映射。比如一个班级中,每个学生的学号跟他的姓名就存在着一一映射的关系,这个模型用map可能轻易描述,很明显学号用int描述,姓名用字符串描述(本篇文章中不用char *来描述字符串,而是采用STL中string来描述),下面给出map描述代码:

Map<int, string> mapStudent;

1.       map的构造函数

map共提供了6个构造函数,这块涉及到内存分配器这些东西,略过不表,在下面我们将接触到一些map的构造方法,这里要说下的就是,我们通常用如下方法构造一个map:

Map<int, string> mapStudent;

2.       数据的插入

在构造map容器后,我们就可以往里面插入数据了。这里讲三种插入数据的方法:

第一种:用insert函数插入pair数据,下面举例说明(以下代码虽然是随手写的,应该可以在VC和GCC下编译通过,大家可以运行下看什么效果,在VC下请加入这条语句,屏蔽4786警告  #pragma warning (disable:4786) )

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

       mapStudent.insert(pair<int, string>(1, “student_one”));

       mapStudent.insert(pair<int, string>(2, “student_two”));

       mapStudent.insert(pair<int, string>(3, “student_three”));

       map<int, string>::iterator  iter;

       for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)

{

       Cout<<iter->first<<”   ”<<iter->second<<end;

}

}

第二种:用insert函数插入value_type数据,下面举例说明

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

       mapStudent.insert(map<int, string>::value_type (1, “student_one”));

       mapStudent.insert(map<int, string>::value_type (2, “student_two”));

       mapStudent.insert(map<int, string>::value_type (3, “student_three”));

       map<int, string>::iterator  iter;

       for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)

{

       Cout<<iter->first<<”   ”<<iter->second<<end;

}

}

第三种:用数组方式插入数据,下面举例说明

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

       mapStudent[1] =  “student_one”;

       mapStudent[2] =  “student_two”;

       mapStudent[3] =  “student_three”;

       map<int, string>::iterator  iter;

       for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)

{

       Cout<<iter->first<<”   ”<<iter->second<<end;

}

}

以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值,用程序说明

mapStudent.insert(map<int, string>::value_type (1, “student_one”));

mapStudent.insert(map<int, string>::value_type (1, “student_two”));

上面这两条语句执行后,map中1这个关键字对应的值是“student_one”,第二条语句并没有生效,那么这就涉及到我们怎么知道insert语句是否插入成功的问题了,可以用pair来获得是否插入成功,程序如下

Pair<map<int, string>::iterator, bool> Insert_Pair;

Insert_Pair = mapStudent.insert(map<int, string>::value_type (1, “student_one”));

我们通过pair的第二个变量来知道是否插入成功,它的第一个变量返回的是一个map的迭代器,如果插入成功的话Insert_Pair.second应该是true的,否则为false。

下面给出完成代码,演示插入成功与否问题

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

Pair<map<int, string>::iterator, bool> Insert_Pair;

       Insert_Pair = mapStudent.insert(pair<int, string>(1, “student_one”));

       If(Insert_Pair.second == true)

       {

              Cout<<”Insert Successfully”<<endl;

       }

       Else

       {

              Cout<<”Insert Failure”<<endl;

       }

       Insert_Pair = mapStudent.insert(pair<int, string>(1, “student_two”));

       If(Insert_Pair.second == true)

       {

              Cout<<”Insert Successfully”<<endl;

       }

       Else

       {

              Cout<<”Insert Failure”<<endl;

       }

       map<int, string>::iterator  iter;

       for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)

{

       Cout<<iter->first<<”   ”<<iter->second<<end;

}

}

大家可以用如下程序,看下用数组插入在数据覆盖上的效果

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

       mapStudent[1] =  “student_one”;

       mapStudent[1] =  “student_two”;

       mapStudent[2] =  “student_three”;

       map<int, string>::iterator  iter;

       for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)

{

       Cout<<iter->first<<”   ”<<iter->second<<end;

}

}

3.       map的大小

在往map里面插入了数据,我们怎么知道当前已经插入了多少数据呢,可以用size函数,用法如下:

Int nSize = mapStudent.size();

4.       数据的遍历

这里也提供三种方法,对map进行遍历

第一种:应用前向迭代器,上面举例程序中到处都是了,略过不表

第二种:应用反相迭代器,下面举例说明,要体会效果,请自个动手运行程序

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

       mapStudent.insert(pair<int, string>(1, “student_one”));

       mapStudent.insert(pair<int, string>(2, “student_two”));

       mapStudent.insert(pair<int, string>(3, “student_three”));

       map<int, string>::reverse_iterator  iter;

       for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)

{

       Cout<<iter->first<<”   ”<<iter->second<<end;

}

}

第三种:用数组方式,程序说明如下

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

       mapStudent.insert(pair<int, string>(1, “student_one”));

       mapStudent.insert(pair<int, string>(2, “student_two”));

       mapStudent.insert(pair<int, string>(3, “student_three”));

       int nSize = mapStudent.size()

//此处有误,应该是 for(int nIndex = 1; nIndex <= nSize; nIndex++) 

//by rainfish

       for(int nIndex = 0; nIndex < nSize; nIndex++)

{

       Cout<<mapStudent[nIndex]<<end;

}

}

5.       数据的查找(包括判定这个关键字是否在map中出现)

在这里我们将体会,map在数据插入时保证有序的好处。

要判定一个数据(关键字)是否在map中出现的方法比较多,这里标题虽然是数据的查找,在这里将穿插着大量的map基本用法。

这里给出三种数据查找方法

第一种:用count函数来判定关键字是否出现,其缺点是无法定位数据出现位置,由于map的特性,一对一的映射关系,就决定了count函数的返回值只有两个,要么是0,要么是1,出现的情况,当然是返回1了

第二种:用find函数来定位数据出现位置,它返回的一个迭代器,当数据出现时,它返回数据所在位置的迭代器,如果map中没有要查找的数据,它返回的迭代器等于end函数返回的迭代器,程序说明

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

       mapStudent.insert(pair<int, string>(1, “student_one”));

       mapStudent.insert(pair<int, string>(2, “student_two”));

       mapStudent.insert(pair<int, string>(3, “student_three”));

       map<int, string>::iterator iter;

       iter = mapStudent.find(1);

if(iter != mapStudent.end())

{

       Cout<<”Find, the value is ”<<iter->second<<endl;

}

Else

{

       Cout<<”Do not Find”<<endl;

}

}

第三种:这个方法用来判定数据是否出现,是显得笨了点,但是,我打算在这里讲解

Lower_bound函数用法,这个函数用来返回要查找关键字的下界(是一个迭代器)

Upper_bound函数用法,这个函数用来返回要查找关键字的上界(是一个迭代器)

例如:map中已经插入了1,2,3,4的话,如果lower_bound(2)的话,返回的2,而upper-bound(2)的话,返回的就是3

Equal_range函数返回一个pair,pair里面第一个变量是Lower_bound返回的迭代器,pair里面第二个迭代器是Upper_bound返回的迭代器,如果这两个迭代器相等的话,则说明map中不出现这个关键字,程序说明

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

       mapStudent[1] =  “student_one”;

       mapStudent[3] =  “student_three”;

       mapStudent[5] =  “student_five”;

       map<int, string>::iterator  iter;

iter = mapStudent.lower_bound(2);

{

       //返回的是下界3的迭代器

       Cout<<iter->second<<endl;

}

iter = mapStudent.lower_bound(3);

{

       //返回的是下界3的迭代器

       Cout<<iter->second<<endl;

}

 

iter = mapStudent.upper_bound(2);

{

       //返回的是上界3的迭代器

       Cout<<iter->second<<endl;

}

iter = mapStudent.upper_bound(3);

{

       //返回的是上界5的迭代器

       Cout<<iter->second<<endl;

}

 

Pair<map<int, string>::iterator, map<int, string>::iterator> mapPair;

mapPair = mapStudent.equal_range(2);

if(mapPair.first == mapPair.second)
       {

       cout<<”Do not Find”<<endl;

}

Else

{

Cout<<”Find”<<endl;
}

mapPair = mapStudent.equal_range(3);

if(mapPair.first == mapPair.second)
       {

       cout<<”Do not Find”<<endl;

}

Else

{

Cout<<”Find”<<endl;
}

}

6.       数据的清空与判空

清空map中的数据可以用clear()函数,判定map中是否有数据可以用empty()函数,它返回true则说明是空map

7.       数据的删除

这里要用到erase函数,它有三个重载了的函数,下面在例子中详细说明它们的用法

#include <map>

#include <string>

#include <iostream>

Using namespace std;

Int main()

{

       Map<int, string> mapStudent;

       mapStudent.insert(pair<int, string>(1, “student_one”));

       mapStudent.insert(pair<int, string>(2, “student_two”));

       mapStudent.insert(pair<int, string>(3, “student_three”));

 

//如果你要演示输出效果,请选择以下的一种,你看到的效果会比较好

       //如果要删除1,用迭代器删除

       map<int, string>::iterator iter;

       iter = mapStudent.find(1);

       mapStudent.erase(iter);

 

       //如果要删除1,用关键字删除

       Int n = mapStudent.erase(1);//如果删除了会返回1,否则返回0

 

       //用迭代器,成片的删除

       //一下代码把整个map清空

       mapStudent.earse(mapStudent.begin(), mapStudent.end());

       //成片删除要注意的是,也是STL的特性,删除区间是一个前闭后开的集合

 

       //自个加上遍历代码,打印输出吧

}

8.       其他一些函数用法

这里有swap,key_comp,value_comp,get_allocator等函数,感觉到这些函数在编程用的不是很多,略过不表,有兴趣的话可以自个研究

9.       排序

这里要讲的是一点比较高深的用法了,排序问题,STL中默认是采用小于号来排序的,以上代码在排序上是不存在任何问题的,因为上面的关键字是int型,它本身支持小于号运算,在一些特殊情况,比如关键字是一个结构体,涉及到排序就会出现问题,因为它没有小于号操作,insert等函数在编译的时候过不去,下面给出两个方法解决这个问题

第一种:小于号重载,程序举例

#include <map>

#include <string>

Using namespace std;

Typedef struct tagStudentInfo

{

       Int      nID;

       String   strName;

}StudentInfo, *PStudentInfo;  //学生信息

 

Int main()

{

    int nSize;

       //用学生信息映射分数

       map<StudentInfo, int>mapStudent;

    map<StudentInfo, int>::iterator iter;

       StudentInfo studentInfo;

       studentInfo.nID = 1;

       studentInfo.strName = “student_one”;

       mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));

       studentInfo.nID = 2;

       studentInfo.strName = “student_two”;

mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));

 

for (iter=mapStudent.begin(); iter!=mapStudent.end(); iter++)

    cout<<iter->first.nID<<endl<<iter->first.strName<<endl<<iter->second<<endl;

 

}

以上程序是无法编译通过的,只要重载小于号,就OK了,如下:

Typedef struct tagStudentInfo

{

       Int      nID;

       String   strName;

       Bool operator < (tagStudentInfo const& _A) const

       {

              //这个函数指定排序策略,按nID排序,如果nID相等的话,按strName排序

              If(nID < _A.nID)  return true;

              If(nID == _A.nID) return strName.compare(_A.strName) < 0;

              Return false;

       }

}StudentInfo, *PStudentInfo;  //学生信息

第二种:仿函数的应用,这个时候结构体中没有直接的小于号重载,程序说明

#include <map>

#include <string>

Using namespace std;

Typedef struct tagStudentInfo

{

       Int      nID;

       String   strName;

}StudentInfo, *PStudentInfo;  //学生信息

 

Classs sort

{

       Public:

       Bool operator() (StudentInfo const &_A, StudentInfo const &_B) const

       {

              If(_A.nID < _B.nID) return true;

              If(_A.nID == _B.nID) return _A.strName.compare(_B.strName) < 0;

              Return false;

       }

};

 

Int main()

{

       //用学生信息映射分数

       Map<StudentInfo, int, sort>mapStudent;

       StudentInfo studentInfo;

       studentInfo.nID = 1;

       studentInfo.strName = “student_one”;

       mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));

       studentInfo.nID = 2;

       studentInfo.strName = “student_two”;

mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));

}

10.   另外

由于STL是一个统一的整体,map的很多用法都和STL中其它的东西结合在一起,比如在排序上,这里默认用的是小于号,即less<>,如果要从大到小排序呢,这里涉及到的东西很多,在此无法一一加以说明。

还要说明的是,map中由于它内部有序,由红黑树保证,因此很多函数执行的时间复杂度都是log2N的,如果用map函数可以实现的功能,而STL  Algorithm也可以完成该功能,建议用map自带函数,效率高一些。

下面说下,map在空间上的特性,否则,估计你用起来会有时候表现的比较郁闷,由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节的,一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑的,相当于平衡二叉树中的平衡因子),我想大家应该知道,这些地方很费内存了吧,不说了……

============================================================
[转载]MSDN

Standard C++ Library Reference  
map::insert, map::find, and map::end  
See Also  Example 
 Collapse All Expand All    Language Filter: All Language Filter: Multiple Language Filter: Visual Basic Language Filter: C# Language Filter: C++ Language Filter: J# Language Filter: JScript  
 Visual Basic (Declaration) 
 Visual Basic (Usage) 
 C# 
 C++ 
 J# 
 JScript 

Illustrates how to use the map::insert, map::find, and map::end Standard Template Library (STL) functions in Visual C++.

 
iterator map::end( ); 
iterator map::find(
   const Key& Key
);
pair<iterator, bool> 
map::insert(
   const value_type& x
);
 

Remarks
Note  
The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.
 

The end function returns an iterator that points one past the end of a sequence. find returns an iterator that designates the first element whose sort key equals Key. If no such element exists, the iterator equals end. If the key does not already exist, insert will add it to the sequence and return pair<iterator, true>. If the key already exists, insert does not add it to the sequence and returns pair <iterator, false>. The following sample creates a map of ints to strings. In this case, the mapping is from digits to their string equivalents (1 -> "One", 2 -> "Two", and so on). The program reads a number from the user, finds the word equivalent for each digit (using the map), and prints the number back as a series of words. For example, if the user enters 25463, the program responds with: Two Five Four Six Three. 

Example
  Copy Code
view plaincopy to clipboardprint?
  1.     
  2. // map_insert_find_end.cpp   
  3. // compile with: /EHsc   
  4. #pragma warning(disable:4786)   
  5. #include <iostream>   
  6. #include <string>   
  7. #include <map>   
  8.   
  9. using namespace std;   
  10.   
  11. typedef map<int, string, less<int> > INT2STRING;   
  12.   
  13. int main()   
  14. {   
  15.    // 1. Create a map of ints to strings  
  16.    INT2STRING theMap;   
  17.    INT2STRING::iterator theIterator;   
  18.    string theString = "";   
  19.    int index;   
  20.   
  21.    // Fill it with the digits 0 - 9, each mapped to its string counterpart  
  22.    // Note: value_type is a pair for maps...  
  23.    theMap.insert(INT2STRING::value_type(0,"Zero"));   
  24.    theMap.insert(INT2STRING::value_type(1,"One"));   
  25.    theMap.insert(INT2STRING::value_type(2,"Two"));   
  26.    theMap.insert(INT2STRING::value_type(3,"Three"));   
  27.    theMap.insert(INT2STRING::value_type(4,"Four"));   
  28.    theMap.insert(INT2STRING::value_type(5,"Five"));   
  29.    theMap.insert(INT2STRING::value_type(6,"Six"));   
  30.    theMap.insert(INT2STRING::value_type(7,"Seven"));   
  31.    theMap.insert(INT2STRING::value_type(8,"Eight"));   
  32.    theMap.insert(INT2STRING::value_type(9,"Nine"));   
  33.   
  34.    // Read a Number from the user and print it back as words  
  35.    for( ; ; )   
  36.    {   
  37.       cout << "Enter \"q\" to quit, or enter a Number: ";   
  38.       cin >> theString;   
  39.       if (theString == "q")   
  40.          break;   
  41.   
  42.       // extract each digit from the string, find its corresponding  
  43.       // entry in the map (the word equivalent) and print it  
  44.       for (index = 0; index < (signed)theString.length(); index++)   
  45.       {   
  46.          theIterator = theMap.find(theString[index] - '0');   
  47.          if (theIterator != theMap.end() )   // is 0 - 9  
  48.             cout << (*theIterator).second << " ";   
  49.          else    // some character other than 0 - 9  
  50.             cout << "[err] ";   
  51.       }         
  52.       cout << endl;   
  53.    }   
  54. }  
[cpp] view plaincopy
  1.    
  2. // map_insert_find_end.cpp  
  3. // compile with: /EHsc  
  4. #pragma warning(disable:4786)  
  5. #include <iostream>  
  6. #include <string>  
  7. #include <map>  
  8.   
  9. using namespace std;  
  10.   
  11. typedef map<int, string, less<int> > INT2STRING;  
  12.   
  13. int main()  
  14. {  
  15.    // 1. Create a map of ints to strings  
  16.    INT2STRING theMap;  
  17.    INT2STRING::iterator theIterator;  
  18.    string theString = "";  
  19.    int index;  
  20.   
  21.    // Fill it with the digits 0 - 9, each mapped to its string counterpart  
  22.    // Note: value_type is a pair for maps...  
  23.    theMap.insert(INT2STRING::value_type(0,"Zero"));  
  24.    theMap.insert(INT2STRING::value_type(1,"One"));  
  25.    theMap.insert(INT2STRING::value_type(2,"Two"));  
  26.    theMap.insert(INT2STRING::value_type(3,"Three"));  
  27.    theMap.insert(INT2STRING::value_type(4,"Four"));  
  28.    theMap.insert(INT2STRING::value_type(5,"Five"));  
  29.    theMap.insert(INT2STRING::value_type(6,"Six"));  
  30.    theMap.insert(INT2STRING::value_type(7,"Seven"));  
  31.    theMap.insert(INT2STRING::value_type(8,"Eight"));  
  32.    theMap.insert(INT2STRING::value_type(9,"Nine"));  
  33.   
  34.    // Read a Number from the user and print it back as words  
  35.    for( ; ; )  
  36.    {  
  37.       cout << "Enter \"q\" to quit, or enter a Number: ";  
  38.       cin >> theString;  
  39.       if (theString == "q")  
  40.          break;  
  41.   
  42.       // extract each digit from the string, find its corresponding  
  43.       // entry in the map (the word equivalent) and print it  
  44.       for (index = 0; index < (signed)theString.length(); index++)  
  45.       {  
  46.          theIterator = theMap.find(theString[index] - '0');  
  47.          if (theIterator != theMap.end() )   // is 0 - 9  
  48.             cout << (*theIterator).second << " ";  
  49.          else    // some character other than 0 - 9  
  50.             cout << "[err] ";  
  51.       }        
  52.       cout << endl;  
  53.    }  
  54. }  
Input
  
12
q
 

Sample Output
  Copy Code 
Enter "q" to quit, or enter a Number: 12
One Two
Enter "q" to quit, or enter a Number: q
 

Requirements
Header: <map>

See Also
Concepts
Standard Template Library Samples

 To make a suggestion or report a bug about Help or another feature of this product, go to the feedback site. 

================================================================
Illustrates how to use the map::max_size, map::clear, map::erase, and map::size Standard Template Library (STL) functions in Visual C++.

 
size_type max_size( ) const; 
void clear( ) const; 
bool empty( ) const; 
iterator erase(
   iterator First,
   iterator Last
);
size_type size( ) const;
A::reference operator[](         // A is the allocator
   const Key& Key
); 
iterator map::begin( );
iterator map::end( );
iterator map::find(
   const Key& Key
);
 

Remarks
Note  
The class/parameter names in the prototype do not match the version in the header file. Some have been modified to improve readability.
 

The following sample creates a map of strings to ints and fills it first with a map of month names to month numbers, and then empties and refills it with a map of weekday names to corresponding ints. 

Example
  Copy Code 
view plaincopy to clipboardprint?
  1. // map_max_size_etc_sample.cpp   
  2. // compile with: /EHsc   
  3. //   
  4. // Functions:    iterator map::max_size();  
  5. //               void clear() const;  
  6. //               bool empty() const;   
  7. //               iterator erase(iterator first, iterator last);  
  8. //               size_type size() const;   
  9. //               A::reference operator[](const Key& key);  
  10. //               iterator map::begin();   
  11. //               iterator map::end();  
  12. //               iterator map::find(const Key& key);  
  13.   
  14. #pragma warning(disable:4786)   
  15.   
  16. #include <iostream>   
  17. #include <string>   
  18. #include <map>   
  19.   
  20. using namespace std ;   
  21.   
  22. typedef map<string, int> STRING2INT;   
  23.   
  24. int main()   
  25. {   
  26.    STRING2INT MyMap;   
  27.    STRING2INT::iterator MyIterator;   
  28.    string MyBuffer;   
  29.   
  30.    // print the maximum number of <key,data> pairs that MyMap can hold  
  31.    cout << "MyMap is capable of holding " << MyMap.max_size()   
  32.         << " <string,int> pairs" << endl;   
  33.   
  34.    if (!MyMap.empty())   
  35.       cout << "MyMap has " << MyMap.size() << " entries" << endl;   
  36.    else  
  37.       cout << "MyMap is empty" << endl;   
  38.       
  39.    cout << "Entering new entries in MyMap" << endl;   
  40.    // Fill in MyMap with the months of the year, mapped to their number  
  41.    // January - 1, February - 2, etc. using operator[].  
  42.    MyMap["January"] = 1;   
  43.    MyMap["February"] = 2;   
  44.    MyMap["March"] = 3;   
  45.    MyMap["April"] = 4;   
  46.    MyMap["May"] = 5;   
  47.    MyMap["June"] = 6;   
  48.    MyMap["July"] = 7;   
  49.    MyMap["August"] = 8;   
  50.    MyMap["September"] = 9;   
  51.    MyMap["October"] = 10;   
  52.    MyMap["November"] = 11;   
  53.    MyMap["December"] = 12;   
  54.   
  55.    if (!MyMap.empty())   
  56.       cout << "MyMap has " << MyMap.size() << " entries" << endl;   
  57.    else  
  58.       cout << "MyMap is empty" << endl;   
  59.   
  60.    // Ask the user for a month of the year and print the number  
  61.    // that corresponds to the month entered  
  62.    MyIterator = MyMap.end();   
  63.    while (MyIterator == MyMap.end())   
  64.    {   
  65.       cout << endl << "Enter a Month: ";   
  66.       cin >> MyBuffer;   
  67.       if ((MyIterator = MyMap.find(MyBuffer)) != MyMap.end())   
  68.          cout << (*MyIterator).first << " is Month Number "  
  69.               << (*MyIterator).second << endl;   
  70.       else  
  71.          cout << "Enter a Valid Month (example: March)" << endl;   
  72.    }   
  73.   
  74.    // empty MyMap - note that clear simply calls erase(begin(),end());  
  75.    MyMap.clear();   
  76.   
  77.    if (!MyMap.empty())   
  78.       cout << "MyMap has " << MyMap.size() << " entries" << endl;   
  79.    else  
  80.       cout << "MyMap is empty" << endl;   
  81.       
  82.    cout << "Entering new entries in MyMap" << endl;   
  83.    // Fill MyMap with the days of the week, each mapped to an int  
  84.    MyMap["Monday"] = 1;   
  85.    MyMap["Tuesday"] = 2;   
  86.    MyMap["Wednesday"] = 3;   
  87.    MyMap["Thursday"] = 4;   
  88.    MyMap["Friday"] = 5;   
  89.    MyMap["Saturday"] = 6;   
  90.    MyMap["Sunday"] = 7;   
  91.   
  92.    if (!MyMap.empty())   
  93.       cout << "MyMap has " << MyMap.size() << " entries" << endl;   
  94.    else  
  95.       cout << "MyMap is empty" << endl;   
  96.   
  97.    // Ask the user for a day of the week and print the number  
  98.    // that corresponds to the day entered   
  99.    MyIterator = MyMap.end();   
  100.    while (MyIterator == MyMap.end())   
  101.    {   
  102.       cout << endl << "Enter a Day of the Week: ";   
  103.       cin >> MyBuffer;   
  104.       if ((MyIterator = MyMap.find(MyBuffer)) != MyMap.end())   
  105.          cout << (*MyIterator).first << " is Day Number "  
  106.               << (*MyIterator).second << endl;   
  107.       else  
  108.          cout << "Enter a Valid Day of the Week(example: Monday)" << endl;   
  109.    }   
  110.   
  111.    // Now clear MyMap again - this time using erase instead of clear  
  112.    MyMap.erase(MyMap.begin(), MyMap.end());   
  113.   
  114.    if (!MyMap.empty())   
  115.       cout << "MyMap has " << MyMap.size() << " entries" << endl;   
  116.    else  
  117.       cout << "MyMap is empty" << endl;   
  118. }  
[cpp] view plaincopy
  1. // map_max_size_etc_sample.cpp  
  2. // compile with: /EHsc  
  3. //  
  4. // Functions:    iterator map::max_size();  
  5. //               void clear() const;  
  6. //               bool empty() const;  
  7. //               iterator erase(iterator first, iterator last);  
  8. //               size_type size() const;  
  9. //               A::reference operator[](const Key& key);  
  10. //               iterator map::begin();  
  11. //               iterator map::end();  
  12. //               iterator map::find(const Key& key);  
  13.   
  14. #pragma warning(disable:4786)  
  15.   
  16. #include <iostream>  
  17. #include <string>  
  18. #include <map>  
  19.   
  20. using namespace std ;  
  21.   
  22. typedef map<string, int> STRING2INT;  
  23.   
  24. int main()  
  25. {  
  26.    STRING2INT MyMap;  
  27.    STRING2INT::iterator MyIterator;  
  28.    string MyBuffer;  
  29.   
  30.    // print the maximum number of <key,data> pairs that MyMap can hold  
  31.    cout << "MyMap is capable of holding " << MyMap.max_size()  
  32.         << " <string,int> pairs" << endl;  
  33.   
  34.    if (!MyMap.empty())  
  35.       cout << "MyMap has " << MyMap.size() << " entries" << endl;  
  36.    else  
  37.       cout << "MyMap is empty" << endl;  
  38.      
  39.    cout << "Entering new entries in MyMap" << endl;  
  40.    // Fill in MyMap with the months of the year, mapped to their number  
  41.    // January - 1, February - 2, etc. using operator[].  
  42.    MyMap["January"] = 1;  
  43.    MyMap["February"] = 2;  
  44.    MyMap["March"] = 3;  
  45.    MyMap["April"] = 4;  
  46.    MyMap["May"] = 5;  
  47.    MyMap["June"] = 6;  
  48.    MyMap["July"] = 7;  
  49.    MyMap["August"] = 8;  
  50.    MyMap["September"] = 9;  
  51.    MyMap["October"] = 10;  
  52.    MyMap["November"] = 11;  
  53.    MyMap["December"] = 12;  
  54.   
  55.    if (!MyMap.empty())  
  56.       cout << "MyMap has " << MyMap.size() << " entries" << endl;  
  57.    else  
  58.       cout << "MyMap is empty" << endl;  
  59.   
  60.    // Ask the user for a month of the year and print the number  
  61.    // that corresponds to the month entered  
  62.    MyIterator = MyMap.end();  
  63.    while (MyIterator == MyMap.end())  
  64.    {  
  65.       cout << endl << "Enter a Month: ";  
  66.       cin >> MyBuffer;  
  67.       if ((MyIterator = MyMap.find(MyBuffer)) != MyMap.end())  
  68.          cout << (*MyIterator).first << " is Month Number "  
  69.               << (*MyIterator).second << endl;  
  70.       else  
  71.          cout << "Enter a Valid Month (example: March)" << endl;  
  72.    }  
  73.   
  74.    // empty MyMap - note that clear simply calls erase(begin(),end());  
  75.    MyMap.clear();  
  76.   
  77.    if (!MyMap.empty())  
  78.       cout << "MyMap has " << MyMap.size() << " entries" << endl;  
  79.    else  
  80.       cout << "MyMap is empty" << endl;  
  81.      
  82.    cout << "Entering new entries in MyMap" << endl;  
  83.    // Fill MyMap with the days of the week, each mapped to an int  
  84.    MyMap["Monday"] = 1;  
  85.    MyMap["Tuesday"] = 2;  
  86.    MyMap["Wednesday"] = 3;  
  87.    MyMap["Thursday"] = 4;  
  88.    MyMap["Friday"] = 5;  
  89.    MyMap["Saturday"] = 6;  
  90.    MyMap["Sunday"] = 7;  
  91.   
  92.    if (!MyMap.empty())  
  93.       cout << "MyMap has " << MyMap.size() << " entries" << endl;  
  94.    else  
  95.       cout << "MyMap is empty" << endl;  
  96.   
  97.    // Ask the user for a day of the week and print the number  
  98.    // that corresponds to the day entered  
  99.    MyIterator = MyMap.end();  
  100.    while (MyIterator == MyMap.end())  
  101.    {  
  102.       cout << endl << "Enter a Day of the Week: ";  
  103.       cin >> MyBuffer;  
  104.       if ((MyIterator = MyMap.find(MyBuffer)) != MyMap.end())  
  105.          cout << (*MyIterator).first << " is Day Number "  
  106.               << (*MyIterator).second << endl;  
  107.       else  
  108.          cout << "Enter a Valid Day of the Week(example: Monday)" << endl;  
  109.    }  
  110.   
  111.    // Now clear MyMap again - this time using erase instead of clear  
  112.    MyMap.erase(MyMap.begin(), MyMap.end());  
  113.   
  114.    if (!MyMap.empty())  
  115.       cout << "MyMap has " << MyMap.size() << " entries" << endl;  
  116.    else  
  117.       cout << "MyMap is empty" << endl;  


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/406236.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Oracle实例和Oracle数据库(Oracle体系结构)

-- --Oracle实例和Oracle数据库(Oracle体系结构) -- /* 对于初接触Oracle 数据库的人来讲&#xff0c;很容易混淆的两个概念即是Oracle 实例和Oracle 数据库。这两 概念不同于SQL sever下的实例与数据库&#xff0c;当然也有些相似之处。只是在SQL server我们根本不需要花费太 …

vue elementui 实现图片上传后拖拽排序功能

vue elementui 实现图片上传后拖拽排序功能

Mysql基础2

清空一个表&#xff0c;自增id从1开始truncate table 表名; 查询 select 列名 from 表名 where 条件 order by 列名 [desc|asc] limit 跳过条数,查多少条 AS 别名 列名 as 新列名 注意as可以省掉不写 NULL值查询 select * from table1 where 字段 is null; 组合列 select conca…

C++ 类访问控制(public/protected/private)

From: http://cnmtjp.blog.51cto.com/204390/36548 C中 public&#xff0c;protected&#xff0c; private 访问标号小结第一&#xff1a;private, public, protected 访问标号的访问范围。private&#xff1a;只能由1.该类中的函数、2.其友元函数访问。不能被任何其他访问&…

vue监听浏览器原生返回按钮,进行路由转跳

vue监听浏览器原生返回按钮&#xff0c;进行路由转跳

WORD关于论文格式设置

现今的论文格式要求越来越无语,封面页 摘要页 目录页 正文页,封面页 摘要页 不能有页眉页脚 目录页 要求倒是不算高,整出个目录就行 正文页 页眉无所谓,但是页脚要显示页码 1 不设置就好,但是有时候设置了页眉又删除了的话,会出现一个横线,这个横线是由 页眉 的样式所定义的,这…

自身经历第二次面试(阿里)

自我介绍 1、哈希表及其实现机制 2、C的三个特征及其解释 3、抽象与接口的区别 4、设计模式 转载于:https://www.cnblogs.com/Vae1990Silence/p/4330577.html

秒杀系统 mysql_秒杀系统-介绍

秒杀系统秒杀系统其实是针对库存做的系统。用户成功秒杀商品&#xff0c;对于我们系统的操作就是减库存和记录用户的购买明细。用户的购买明细包括记录谁购买成功、购买成功的时间和付款信息。而对于减库存操作&#xff0c;需要考虑到以下两个问题&#xff1a;(1)若是用户成功秒…

MOSS中自定义WebService

(转http://tech.ddvip.com/2008-10/122527111786701.html&#xff0c;更详细见msdn&#xff1a;http://msdn.microsoft.com/zh-cn/library/ms464040.aspx) MOSS中已经提供的webservice都放在虚拟目录_vti_bin中&#xff0c;对应的物理目录为c:Program FilesCommon FilesMicroso…

C语言排序算法总结

From: http://www.diybl.com/course/6_system/linux/Linuxjs/20091028/180420.html 排序算法一直都是让我头疼的算法。为了全面掌握排序算法&#xff0c;我就整理了常用的排序算法。 首先我们来了解一些基本概念&#xff1a; &#xff08;1&#xff09;稳定排序和非稳定排序 简…

js计算数组中每个元素出现的次数(2种方法)

js计算数组中每个元素出现的次数&#xff08;2种方法&#xff09; js动态生成唯一id Javascript生成全局唯一标识符&#xff08;GUID,UUID&#xff09;的方法

执行execute时对象名 retime_record 无效_MyBatis 的执行流程怎么可以讲的这么透彻

前言MyBatis可能很多人都一直在用&#xff0c;但是MyBatis的SQL执行流程可能并不是所有人都清楚了&#xff0c;那么既然进来了&#xff0c;通读本文你将收获如下&#xff1a;1、Mapper接口和映射文件是如何进行绑定的2、MyBatis中SQL语句的执行流程3、自定义MyBatis中的参数设置…

iOS统计项目的代码总行数

如果要统计ios开发代码&#xff0c;包括头文件的&#xff0c;CD到项目目录下&#xff0c;命令如下 ① 列出每个文件的行数 find . -name "*.m" -or -name "*.h" -or -name "*.xib" -or -name "*.c" |xargs wc -l ② 列出代码行数总和f…

C/C++中预编译#,##,#error作用

From: http://bluefairy218.blog.163.com/blog/static/313917532008456397524/ #是生成字符串&#xff1a; #define a(x) #x a(bc) > "bc" ##是连接&#xff1a; #define a(x) abc##x a(123) > abc123 #error是生成…

WCF安全之ASP.NET兼容模式

本文是利用ASP.NET兼容模式实现WCF安全的一个完整示例&#xff0c;其中用到了ASP.NET的Forms身份验证及Membership&#xff0c;并启用了角色管理。 由于整套安全方案完全利用ASP.NET相关功能实现&#xff0c;而未用到WCF安全策略相关的包括WCF身份验证、WCF授权及WCF传输安全等…