标准模板类(STL)(二),具体容器简介

(二)容器的具体介绍

A、顺序式容器

1、vector

该标准容器是一个定义在 namespace std 中的模板,该模板的原型声明在头文件 <vector> 中。它的数据结构很像一个数组,所以与其他容器相比,vector 能非常方便和高效访问单个元素。因此,在 vector 中提供随机访问循环子。

说明:实际上就是个动态数组。随机存取任何元素都能在常数时间完成。在尾端增删元素具有较佳的性能。例1:

int main()  

{ int i;

 int a[5] = {1,2,3,4,5 };    

    vector<int>  v(5);

 cout << v.end()-v.begin() << endl;

 for( i = 0;i < v.size();i ++ )  v[i] = i;

 v.at(4) = 100;

 for( i = 0;i < v.size();i ++ )

 cout << v[i] << "," ;

 cout << endl;

 vector<int> v2(a,a+5);  //构造函数

 v2.insert( v2.begin() + 2, 13 ); //在begin()+2位置插入 13

 for( i = 0;i < v2.size();i ++ )

 cout << v2[i] << "," ;    

return 0;

}

输出:

5

0,1,2,3,100,

1,2,13,3,4,5,

例2:

int main()  {

 const int SIZE = 5;

 int a[SIZE] = {1,2,3,4,5 }; 

 vector<int> v (a,a+5);  //构造函数

 try {

  v.at(100) = 7;

 }

 catch( out_of_range e) {

  cout << e.what() << endl;

 }

 cout << v.front() << “,” << v.back() << endl;

 v.erase(v.begin());

 ostream_iterator<int> output(cout ,“*");

 copy (v.begin(),v.end(),output);

 v.erase( v.begin(),v.end());  //等效于 v.clear();

 if( v.empty ())

  cout << "empty" << endl;

 v.insert (v.begin(),a,a+SIZE);

 copy (v.begin(),v.end(),output);

}  

// 输出:

invalid vector<T> subscript

1,5

2*3*4*5*empty

1*2*3*4*5*

ostream_iterator<int> output(cout ,“*");//定义了一个 ostream_iterator 对象,可以通过cout输出以 * 分隔的一个个整数

copy (v.begin(),v.end(),output);//导致v的内容在 cout上输出

copy 函数模板(算法):

template<class InIt, class OutIt> 

OutIt copy(InIt first, InIt last, OutIt x); //本函数对每个在区间[0, last - first)中的N执行一次 *(x+N) = * ( first + N) ,返回 x + N

对于copy (v.begin(),v.end(),output);

first 和 last 的类型是  vector<int>::const_iterator,output 的类型是 ostream_iterator<int> 

例3

#include "iostream"

#include "vector"

#include "algorithm"

using namespace std;

int main()

{

istream_iterator<int>inputInt(cin);

int n1,n2;

n1=*inputInt;

inputInt++;

n2=*inputInt;

cout<<n1<<" "<<n2<<endl;

ostream_iterator<int>outputInt(cout);

*outputInt=n1+n2;

cout<<endl;

int a[5]={1,2,3,4,5};

copy(a,a+5,outputInt);

return 1;

}

输出结果为:

78,90

168

12345

2、list

该标准容器是一个定义在 namespace std 中的模板,该模板的原型声明在头文件 <list> 中。list 是一个对容器元素的插入和删除操作进行了优化的序列。但与 vector 和 deque 相比,对元素的下标访问操作的低效是不能容忍的,因此 list 不提供这类操作,即不提供随机访问循环子,而提供双向循环子。这意味着 list 是典型的通过使用双链表实现的序列结构。

说明:双向链表,在任何位置增删元素都能在常数时间完成。不支持随机存取。  

对于 list,front 操作和 back 操作都同样高效和方便。因此,如果希望使用 list 编写的代码演变为能应用于多种其他容器的通用代码,则使用更具广泛适用性的 back 操作是最好的选择。list 元素的插入和删除操作尤为高效,所以 list 更适合在插入和删除操作频繁的应用中使用。

#include "list"

#include "iostream"

using namespace std;

typedef list<int> LISTINT;

int main()

{

int rgTest1[] = {5,6,7};

int rgTest2[] = {10,11,12};

LISTINT listInt;

LISTINT::iterator i;

// Insert one at a time

listInt.insert (listInt.begin(), 2);

listInt.insert (listInt.begin(), 1);

listInt.insert (listInt.end(), 3);

// output: 1 2 3

cout << "listInt:";

for(i=listInt.begin();i!=listInt.end();i++)

 cout << " " << *i;

cout <<endl;

// Insert 3 fours

listInt.insert(listInt.end(),3,4);

// output: 1 2 3 4 4 4

cout <<"listInt:";

for (i=listInt.begin();i!=listInt.end();++i)

 cout <<" "<< *i;

cout<<endl;

// Insert an array at the end

listInt.insert(listInt.end(),rgTest1,rgTest1+3);

// output: 1 2 3 4 4 4 5 6 7

cout << "listInt:";

for (i=listInt.begin(); i!=listInt.end();++i)

 cout << " " << *i;

cout <<endl;

// Insert another LISTINT

LISTINT listAnother;

listAnother.insert (listAnother.begin(),rgTest2,rgTest2+3);

listInt.insert (listInt.end(), listAnother.begin(), listAnother.end());

// output: 1 2 3 4 4 4 5 6 7 10 11 12

cout << "listInt:";

for (i=listInt.begin();i!=listInt.end();++i)

 cout <<" "<<*i;

cout <<endl;

return 1;

}

3、deque

       该标准容器是一个定义在 namespace std 中的模板,该模板的原型声明在头文件 <deque> 中。deque 是一个双向队列,也是一个优化序列。在 deque 两端的操作与 list 一样高效,对元素的下标操作的效率又与 vector 类似,而对容器元素的插入和删除操作的效率则介于 list 和 vector 之间。

说明:也是个动态数组,随机存取任何元素都能在常数时间完成(但性能次于vector)。在两端增删元素具有较佳的性能。

      所有适用于vector的操作都适用于deque。deque还有push_front(将元素插入到前面)和pop_front(删除最前面的元素)操作

上述三种容器称为顺序容器,是因为元素的插入位置同元素的值无关。

B、关联式容器

关联式容器内的元素是排序的,插入任何元素,都按相应的排序准则来确定其位置。关联式容器的特点是在查找时具有非常好的性能。

set 即集合,set中不允许相同元素,multiset中允许存在相同的元素。

map与set的不同在于map中存放的是成对的key/value,并根据key对元素进行排序,可快速地根据key来检索元素;map同multimap的不同在于是否允许多个元素有相同的key值。

上述4种容器通常以平衡二叉树方式实现,插入和检索的时间都是 O(logN)。

       内部元素有序排列,新元素插入的位置取决于它的值,查找速度快。

        map关联数组:元素通过键来存储和读取;

      set大小可变的集合,支持通过键实现的快速读取。

        multimap支持同一个键多次出现的map类型;

        multiset支持同一个键多次出现的set类型。

与顺序容器的本质区别

       关联容器是通过键(key)存储和读取元素的,它要求定义一个比较操作进行元素操作。而顺序容器则通过元素在容器中的位置顺序存储和访问元素。 

4、map该标准关联容器是一个定义在 namespace std 中的模板,该模板的原型声明在头文件 <map> 中。 map 是一个元素对(关键字,映射值)序列(注:Hash table (key, value pairs)),它提供了以关键字为基础的快速检索。map 中的每一个关键字必须是唯一的。map 提供双向循环子。

元素按照关键字升序排列,缺省情况下用 less 定义“小于”。

可以用pairs[key] 访形式问map中的元素。pairs 为map容器名,key为关键字的值。该表达式返回的是对关键值为key的元素的值的引用。(我们可以理解为map中存储的数据类型是pairs型)

如果没有关键字为key的元素,则会往pairs里插入一个关键字为key的元素,并返回其值的引用如:

map<int,double>  pairs;

则 pairs[50] = 5; 会修改pairs中关键字为50的元素,使其值变成5。

例一:

#include <iostream>

#include <map>

using namespace std;

ostream & operator <<( ostream & o,const pair<  int,double> & p)

{

 o << "(" << p.first  << "," << p.second << ")";

 return o;

}

int main()  {

 typedef map<int,double,less<int> > mmid;

 mmid pairs;

 cout << "1) " << pairs.count(15) << endl;

 pairs.insert(mmid::value_type(15,2.7));

 pairs.insert(make_pair(15,99.3));//make_pair生成pair对象

 cout << "2) " << pairs.count(15) << endl;

 pairs.insert(mmid::value_type(20,9.3));

  mmid::iterator i;

       cout << "3) ";

       for( i = pairs.begin(); i != pairs.end();i ++ )

      cout << * i  << ",";

 cout << endl;

 cout << "4) ";

 int n =  pairs[40];//如果没有关键字为40的元素,则插入一个

 for( i = pairs.begin(); i != pairs.end();i ++ )

  cout << * i  << ",";

 cout << endl;

 cout << "5) ";

 pairs[15] = 6.28; //把关键字为15的元素值改成6.28

 for( i = pairs.begin(); i != pairs.end();i ++ )

  cout << * i  << ",";

            return 0;

}

例二:

#include <iostream>

#include "numeric"

#include "string"

#include "map"

using namespace std;

typedef map<int,string,less<int> > INT2STRING;

int main()

{

INT2STRING theMap;

INT2STRING::iterator theIterator;

string theString="";

int index;

theMap.insert(INT2STRING::value_type(0,"Zero"));

theMap.insert(INT2STRING::value_type(1,"One"));

theMap.insert(INT2STRING::value_type(2,"Two"));

theMap.insert(INT2STRING::value_type(3,"There"));

theMap.insert(INT2STRING::value_type(4,"Four"));

theMap.insert(INT2STRING::value_type(5,"Five"));

theMap.insert(INT2STRING::value_type(6,"Six"));

theMap.insert(INT2STRING::value_type(7,"Seven"));

theMap.insert(INT2STRING::value_type(8,"Eight"));

theMap.insert(INT2STRING::value_type(9,"Nine"));

for(;;)

   {

   cout<<"ENter \"q\" to quit,or enter a number:\n";

   cin>>theString;

   if(theString=="q")

    break;

   for(index=0;index<theString.length();index++){

   theIterator=theMap.find(theString[index]-'0');

   if(theIterator!=theMap.end())

    cout<<(*theIterator).second<<" ";

   else

    cout<<"[err]";

   }

   cout<<endl;

   }

return 1; 

}

发布了208 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/hopegrace/article/details/104154468
今日推荐