这是微软帮助文档中对集合(set)的解释: “描述了一个控制变长元素序列的对象的模板类,每一个元素包含了一个排序键(sort key)和一个值(value)。对这个序列可以进行查找、插入、删除序列中的任意一个元素,而完成这些操作的时间同这个序列中元素个数的对数成比例关 系,并且当游标指向一个已删除的元素时,删除操作无效。”
STL的大三主体:算法、容器、迭代器。C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构操作。vector封装数组,list封装了链表,map和set封装了二叉树等,在封装这些数据结构的时候,STL按照程序员的使用习惯,以成员函数方式提供的常用操作,如:插入、排序、删除、查找等。让用户在STL使用过程中,并不会感到陌生。
vector(向量)——STL中标准而安全的数组。只能在vector 的“前面”增加数据。
deque(双端队列double-ended queue)——在功能上和vector相似,但是可以在前后两端向其中添加数据。
list(列表)——游标一次只可以移动一步。如果你对链表已经很熟悉,那么STL中的list则是一个双向链表(每个节点有指向前驱和指向后继的两个指针)。
set(集合)——包含了经过排序了的数据,这些数据的值(value)必须是唯一的。
map(映射)——经过排序了的二元组的集合,map中的每个元素都是由两个值组成,其中的key(键值,一个map中的键值必须是唯一的)是在排序 或搜索时使用,它的值可以在容器中重新获取;而另一个值是该元素关联的数值。比如,除了可以ar[43] = "overripe"这样找到一个数据,map还可以通过ar["banana"] = "overripe"这样的方法找到一个数据。如果你想获得其中的元素信息,通过输入元素的全名就可以轻松实现。
multiset(多重集)——和集合(set)相似,然而其中的值不要求必须是唯一的(即可以有重复)。
multimap(多重映射)——和映射(map)相似,然而其中的键值不要求必须是唯一的(即可以有重复)。
注意:如果你阅读微软的帮助文档,你会遇到对每种容器的效率的陈述。比如:log(n*n)的插入时间。除非你要处理大量的数据,否则这些时间的影响是可 以忽略的。如果你发现你的程序有明显的滞后感或者需要处理时间攸关(time critical)的事情,你可以去了解更多有关各种容器运行效率的话题。
1.迭代器:
Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。或者这样说可能更容易理解:Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器不仅仅是指针,因此你不能认为他们一定具有地址值。例如,一个数组索引,也可以认为是一种迭代器。
迭代器的类型
对于STL数据结构和算法,你可以使用五种迭代器。下面简要说明了这五种类型:
· Input iterators 提供对数据的只读访问。只能单步向前迭代元素,不允许修改由该类迭代器引用的元素。
· Output iterators 提供对数据的只写访问。只能单步向前迭代元素,不同的是该类迭代器对元素只有写的权力。
· Forward iterators 提供读写操作,并单步向前迭代元素。(set/map)
· Bidirectional iterators提供读写操作,并能向前和向后操作。(list)
· Random access iterators提供读写操作,并能在数据中随机移动。该类迭代器能完成上面所有迭代器的工作,它自己独有的特性就是可以像指针那样进行算术计算,而不是仅仅只有单步向前或向后迭代。(vector\deque)
reverse iterator:取决于你这个容器本身的迭代器是什么类型。但是至少是bidirectional的(不然我怎么逆向啊?)
insert iterator:属于output iterator;
istream iterator:属于input iterator;
ostream iterator:属于output iterator。
forward iterator没有完全继承output iterator的所有功能,只是继承了大部分功能而已。
尽管各种不同的STL实现细节方面有所不同,还是可以将上面的迭代器想象为一种类继承关系。从这个意义上说,下面的迭代器继承自上面的迭代器。由于这种继承关系,你可以将一个Forward迭代器作为一个output或input迭代器使用。同样,如果一个算法要求是一个bidirectional 迭代器,那么只能使用该种类型和随机访问迭代器。
vector迭代器的自增和解引用运算
迭代器类型定义了一些操作来获取迭代器所指向的元素,并允许程序员将迭代器从一个元素移动到另一个元素。
迭代器类型可使用解引用操作符(*操作符)来访问迭代器所指向r 元素:
*iter = 0;
解引用操作符返回迭代器当前所指向的元素。假设iter指向vector对象ivec的第一个元素,那么*iter和ivec[0]就是指向同一个元素。上面这个语句的效果就是把这个元素的值赋为0。
迭代器使用自增操作符(1.4.1节)向前移动迭代器指向容器中下一个元素。从逻辑上说,迭代器的自增操作和int型对象的自增操作类似。对 int对象来说,操作结果就是把int型值“加1”,而对迭代器对象则是把容器中的迭代器“向前移动一个位置”。因此,如果iter指向第一个元素, 则++iter指向第二个元素。
如果迭代器到达了容器中的最后一个元素的后面,则迭代器变成past-the-end值。使用一个past-the-end值得指针来访问对象是非法的,就好像使用NULL或为初始化的指针一样。
***每个容器必须带有一些东西,以配合迭代器这个概念来使用
iterator 正向迭代器
const_iterator 正向只读迭代器(只能用于读取容器内的元素,不能改变其值)
reverse_iterator 逆向迭代器(这种特殊的迭代器提供一种逆向的访问——它是倒着走的。它的++操作符是往前回退,而--操 作符是往后移动,与正常的迭代器刚好相反)
const_reverse_iterator 逆向只读迭代器(只能用于读取容器内的元素,不能改变其值)
difference_type 同一容器上两个迭代器相减结果类型
pointer 容器中元素类型的指针
reference 容器中元素类型的引用
const_reference 容器中元素类型的常量引用
size_type 容器中用来统计元素个数的类型
value_type 容器中保存元素的类型,如vector<int>::value_type 等价于int
声明:set<string>::iterator it = dict.begin();
任何容器的erase操作 | 被erase的位置的迭代器失效; |
vector的push_back操作 | 可能没事,但是一旦引发内存重分配,所有迭代器都会失效; |
vector的insert操作 | 插入点之后的所有迭代器失效;但一旦引发内存重分配,所有迭代器都会失效; |
vector的erase操作 | 插入点之后的所有迭代器失效; |
vector的reserve操作 | 所有迭代器失效(因为它导致内存重分配); |
deque的insert操作 | 所有迭代器失效; |
deque的erase操作 | 所有迭代器失效; |
2.优先队列:
①定义:是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素
②使用方法:
priority_queue<int> q; 大的数优先级高
priority_queue<int, vector<int>, cmp> q2; 自定义优先级,以下是重载函数
struct cmp
{
bool operator()(int &x,int &y)
{
return x > y;
}
};
③操作命令:
empty():如果队列为空返回真
pop():删除对顶元素
push():加入一个元素
size():返回优先队列中拥有的元素个数
top():返回优先队列对顶元素(无front函数)
注意:越小的整数优先级越大:priority_queue<int,vector<int>,great<int> > pq (最后两个<不能连在一起,否则会被编译器认为是cin)
④例题(UVA-10954 优先队列+贪心)
#include <iostream>
#include <cstdio>
#include<queue>
using namespace std;
struct cmp
{
bool operator()(int &x,int &y)
{
return x > y;
}
};
int num[5005];
int main()
{
int n;
while(cin>>n && n)
{
for(int i = 0;i < n;i++)
cin>>num[i];
int sum = 0;
priority_queue<int,vector<int>,cmp> shu;
for(int i = 0;i < n;i++)
shu.push(num[i]);
while(1)
{
int temp = shu.top();
shu.pop();
int tsum = temp + shu.top();
shu.pop();
sum += tsum;
if(shu.empty()) break;
shu.push(tsum);
}
printf("%d\n",sum);
}
return 0;
}
3.map容器:
map(const map& m) // 拷贝构造函数
map(iterator begin, iterator end ); //区间构造函数
map(iterator begin, iterator end, const traits& _compare) //带比较谓词的构造函数
map(iterator begin, iterator end, const traits& _compare, const allocator& all) //带分配器
enumMap.insert(map<int, Cstring>::value_type (1, “One”));//用insert方法插入value_type对象
enumMap[1] = "One";enumMap[2] = "Two";//用数组方式插入值
iterator->first 关键字(key)
iterator->second 存储的数据(value)
reverse_iterator rend() 返回一个指向map头部的逆向迭代器
iterator find(const key_type& k) ;//查找一个元素,返回指定元素出现的位置,如果没有返回end()
iterator erase(iterator first, iterator last); //删除一个范围
size_type erase(const Key& key); //通过关键字删除
pair<iterator, iterator> equal_range(const key_type& k);//返回特殊条目的迭代器对
swap() 交换两个map
value_compare value_comp() 返回比较元素value的函数
4.set容器:
set中的key和value是Key类型的,而map中的key和value是一个pair结构中的两个分量。set集合容器实现了红黑树(Red-Black Tree)的平衡二叉检索树的的数据结构,在插入元素时,它会自动调整二叉树的排列,把该元素放到适当的位置,以确保每个子树根节点的键值大于左子树所有节点的键值,而小于右子树所有节点的键值;另外,还得确保根节点的左子树的高度与右子数的高度相等,这样,二叉树的高度最小,从而检索速度最快。要注意的是,它不会重复插入相同键值的元素,而采取忽略处理。
set(const Compare& comp);//构造一个空的set容器。使用comp作为关键字比较函数。
set(const set<Key, Compare, Alloc> & x);//使用x初始化一个set容器。
template <class InputIterator> set(InputIterator first, InputIterator last);//使用迭代器[first, last)指代的元素构造set容器。
template <class InputIterator> set(InputIterator first, InputIterator last, const Compare & comp);使用迭代器[first, last)指代的元素构造set容器。并使用comp作为关键字比较函数。
运算符:
v1 == v2
v1 != v2
v1 <= v2
v1 >= v2
v1 < v2
v1 > v2
v[]
两个set被认为是相等的,如果: 它们具有相同的容量,所有相同位置的元素相等.set之间大小的比较是按照词典规则.
#include <set>
#include <iostream>
#define len 5
using namespace std;
int print(set <int> c)
//用于打印一个 set
{
set <int>::const_iterator cp;
for(cp=c.begin ();cp!=c.end ();cp++)
//让 cp 从 c 的开始到结束打印 cp 对应的值
cout<<*cp<<" ";
return 0;
}
int main()
{
set <int> ctr;
set <int>::iterator cp;
set <int>::reverse_iterator rcp;
int i;
for(i=0;i<len;i++ )ctr.insert(i);
//下面先给 ctr 赋值
cout<<"ctr is:";
print(ctr);
//调用子程序,把 ctr 打印出来
cout<<endl;
cout<<"Its reverse is:";
for(rcp=ctr.rbegin ();rcp!=ctr.rend ();rcp++)
//打印出反向 set 容器
cout<<*rcp<<" ";
cout<<endl;
return 0;
}
reverse_iterator
rend()
//反向迭代器,指向set第一个元素前一个位置
#include <set>
#include <iostream>
using namespace std;
int print(set <int> c) //用于打印一个set
{
set <int>::const_iterator cp;
for(cp=c.begin();cp!=c.end();cp++) //让cp从c的开始到结束打印cp对应的值
cout<<*cp<<" "; return 0;
}
int main()
{
set <int> ctr;
pair <set <int>::const_iterator, set <int>::const_iterator> p;
int i;
for(i=0;i<=3;i++)ctr.insert(i); //给ctr赋值
cout<<"The ctr is: ";
print(ctr); //调用子程序来打印ctr的内容
cout<<endl;
p=ctr.equal_range(2);
if(p.first!=ctr.end()) { cout<<"The first element which key >= 2 is: ";cout<<*p.first; //调用子程序来打印一项 cout<<endl; }
if(p.second!=ctr.end()) { cout<<"The first element which key > 2 is: "; cout<<*p.second; cout<<endl; }
return 0;
}
size_type size() const;//返回储存数据的个数
#include <set>
#include <iostream>
using namespace std;
int main()
{
set <int> ctr;
set <int,less<int>>::key_compare kc = ctr.key_comp()
if(kc(1, 2))
cout<<"kc(1,2) is true"<<endl;
else
cout<<"kc(1,2) is false"<<endl;
return 0;
}
#include <iostream>
#include <set>
int main ()
{
std::set<int> myset;
std::set<int>::value_compare mycomp = myset.value_comp();
for (int i=0; i<=5; i++) myset.insert(i);
std::cout << "myset contains:";
int highest=*myset.rbegin();
std::set<int>::iterator it=myset.begin();
do {
std::cout << ' ' << *it;
} while ( mycomp(*(++it),highest) );
std::cout << '\n';
return 0;
}
iterator clear() //清空该集合
iterator erase(iterator _Where); //输入删除元素的迭代器,返回一个指向第一个没被删除的元素的双向定位器,如果不存在这样的元素,则返回set容器的末尾
iterator erase(iterator _First,iterator _Last); /输入删除元素区间的迭代器,返回一个指向第一个没被删除的元素的双向定位器,如果不存在这样的元素,则返回set容器的末尾
size_type erase(const key_type & _Key); //输入删除元素的关键字,返回被删除的元素的个数
set<int> myset;
set<int>::iterator it;
for (int i=1; i<10; i++) myset.insert(i*10); // 10 20 30 40 50 60 70 80 90
it=myset.begin();
it++;
myset.erase (it); //删除it位置的数据
myset.erase (40); //删除40这个数据
int myints[]={12,75,10,32,20,25};
set<int> c1 (myints,myints+3); // 10,12,75
set<int> c2 (myints+3,myints+6); // 20,25,3
c1.swap(c2);//交换c1与c2的元素 此时c1包括 20,25,32 c2包括10,12,75
#include <set>
#include <iostream>
using namespace std;
int main()
{
set <char> ctr;
ctr.insert('a');
set <char> ctr2(less<char>(),ctr.get_allocato());
cout<<"ctr2's size is: "<<ctr2.size<<endl;
return 0;
}
#include <iostream>
#include <set>
#include <string>
int main ()
{
std::set<std::string> myset;
auto it = myset.cbegin();
myset.emplace_hint (it,"alpha");
it = myset.emplace_hint (myset.cend(),"omega");
it = myset.emplace_hint (it,"epsilon");
it = myset.emplace_hint (it,"beta");
std::cout << "myset contains:";
for (const std::string& x: myset)
std::cout << ' ' << x;
std::cout << '\n';
return 0;
}
5.vector容器:
构造函数:
vector();//无参数 - 构造一个空的vectorvector( size_type num);//数量(num) - 构造一个初始放入num个值的Vector,size为10
vector( size_type num, const TYPE &val );//数量(num)和值(val) - 构造一个初始放入num个值为val的元素的Vector
vector( const vector &from );//vector(from) - 构造一个与vector from 相同的vector
vector( input_iterator start, input_iterator end );//迭代器(start)和迭代器(end) - 复制[start,end)区间内另一个数组的元素到vector中,可以是数组的指针
运算符:
v1 == v2
v1 != v2
v1 <= v2
v1 >= v2
v1 < v2
v1 > v2
v[]
两个vectors被认为是相等的,如果: 它们具有相同的容量,所有相同位置的元素相等.vectors之间大小的比较是按照词典规则.
增加函数:
void push_back( const TYPE &val );//添加值为val的元素到当前vector末尾
iterator insert( iterator loc, const TYPE &val );//在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器,
void insert( iterator loc, size_type num, const TYPE &val );//在指定位置loc前插入num个值为val的元素
void insert( iterator loc, input_iterator start, input_iterator end );//在指定位置loc前插入相同类型变量区间[start, end)的所有元素 .
删除函数:
void clear();//删除当前vector中的所有元素.
iterator erase( iterator loc );//删指定位置loc的元素。返回值是指向删除的最后一个元素的下一位置的迭代器.
iterator erase( iterator start, iterator end );//删除区间[start, end)的所有元素.返回值是指向删除的最后一个元素的下一位置的迭代器.
void pop_back();//删除当前vector最末的一个元素。
遍历函数:
TYPE at( size_type loc );//返回当前Vector指定位置loc的元素的引用. at() 函数 比 [] 运算符更加安全, 因为它不会让你去访问到Vector内越界的元素. 如果试图访问内存里非法值,at() 函数能够辨别出访问是否越界并在越界的时候抛出一个异常out_of_range.
TYPE back();//返回当前vector最末一个元素的引用
iterator begin();//返回一个指向当前vector起始元素的迭代器.
iterator end();//返回一个指向当前vector末尾元素的下一位置的迭代器.注意,如果你要访问末尾元素,需要先将此迭代器自减1.
TYPE front();//返回当前vector起始元素的引用
reverse_iterator rbegin();//返回指向当前vector末尾的逆迭代器.(译注:实际指向末尾的下一位置,而其内容为末尾元素的值,详见逆代器相关内容)
reverse_iterator rend();//回指向当前vector起始位置的逆迭代器.
for_each( v1.begin(), v1.end(), print );
使用算法的时候,可以使用函数对象,例如
class OutPut
{
public:
void operator ()( double i )
{
std::cout << i;
}
}
for_each( v1.begin(), v1.end(), OutPut );
判断函数:
bool empty();//如果当前vector没有容纳任何元素,则empty()函数返回true,否则返回false.
大小函数:
size_type size();//返回当前vector所容纳元素的数目(不是所能容纳元素数目)
size_type capacity();//返回当前vector在重新进行内存分配以前所能容纳的元素数量.
如果你想知道一个vector或string中有多少没有被占用的内存,你必须从capacity()中减去size()。如果size和capacity返回同样的值,容器中就没有剩余空间了,而下一次插入(通过insert或push_back等)会引发上面的重新分配步骤。
size_type max_size();//返回当前vector所能容纳元素数量的最大值(译注:包括可重新分配内存).
其他函数:
void assign( input_iterator start, input_iterator end );//将迭代器[start, end)的元素赋到当前vector
void assign( size_type num, const TYPE &val );//赋num个值为val的元素到vector中.这个函数将会清除掉为vector赋值以前的内容
allocator_type get_allocator();//返回当前vector的内存分配器.在STL里面一般不会调用new或者alloc来分配内存,而且通过一个allocator对象的相关方法来分配.
void reserve( size_type size );//reserve()函数为当前vector预留至少共容纳size个元素的空间.(译注:实际空间可能大于size)
void resize( size_type size);//改变当前vector的大小为size。如果n小于当前大小,容器尾部的元素会被销毁。
void resize( size_type size, TYPE val );//改变当前vector的大小为size,且对新创建的元素赋值val
resize 与reserve的区别
reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用push_back()/insert()函数。
resize是改变容器的大小,并且创建对象,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。
扩大新元素时,如果超过当前的容量,则容量会自动扩充2倍,如果2倍容量仍不足,则继续扩大2倍。包括重新配置、元素移动、释放原始空间的过程。因此对vector容器而言,当增加新的元素时,有可能很快完成(直接存在预留空间中),有可能稍慢(扩容后再放新元素);对修改元素值而言是较快的;对删除元素来说,弱删除尾部元素较快,非尾部元素稍慢,因为牵涉到删除后的元素移动。而进行pop_back操作时,capacity并不会因为vector容器里的元素减少而有所下降,还会维持操作之前的大小。对于vector容器来说,如果有大量的数据需要进行push_back,应当使用reserve()函数提前设定其容量大小,否则会出现许多次容量扩充操作,导致效率低下。
void swap( vector &from );//交换当前vector与vector from的元素
void swap( vector &from1,vector &from2 );//交换vector form1与vector from2的元素
vector迭代器的几种失效的情况:
a.当插入(push_back)一个元素后,end操作返回的迭代器肯定失效。
b.当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时first和end操作返回的迭代器都会失效。
c.当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。
原则:尽量使用区间成员函数代替它们的单元素参数兄弟成员函数
原则:使得容器中元素的拷贝操作轻量而正确,拷贝是STL中容器的运行的基本方式,将元素加入到容器,必然保持一个拷贝,容器中的元素不再是原来的那个元素,所以如果将指针加入容器,必须在容器离开作用域以前删除指针所指的对象。
原则:必须是已存在的元素才能用下标操作符进行索引。
原则:注意对于 vector,任何插入删除操作都会引起迭代器失效。所以要小心。
原则:不要使用auto_ptr作为模板参数来建立容器,这会产生意想不到的陷阱,因为auto_ptr的拷贝有特殊的语义
原则:避免使用vector<bool>, 因为它不能当作标准容器来用
原则:尽量使用标准容器自带的算法代替公共算法。
原则:尽量使用reserve来减少不必要的内存分配次数。
原则:使用erase-remove惯用法删除元素 v1.erase( remove(v1.begin(), v1.end(), 3.0), v1.end() );
原则:尽量使用empty而不是size()==0 来判断容器是否为空
使用“交换技巧”来修整vector过剩空间/内存:
有一种方法来把它从曾经最大的容量减少到它现在需要的容量。这样减少容量的方法常常被称为“收缩到合适(shrink to fit)”。该方法只需一条语句:vector<int>(ivec).swap(ivec);
表达式vector<int>(ivec)建立一个临时vector,它是ivec的一份拷贝:vector的拷贝构造函数做了这个工作。但是,vector的拷贝构造函数只分配拷贝的元素需要的内存,所以这个临时vector没有多余的容量。然后我们让临时vector和ivec交换数据,这时我们完成了,ivec只有临时变量的修整过的容量,而这个临时变量则持有了曾经在ivec中的没用到的过剩容量。在这里(这个语句结尾),临时vector被销毁,因此释放了以前ivec使用的内存,收缩到合适。
用swap方法强行释放STL Vector所占内存:
template < class T> void ClearVector( vector<T>& v )
{
vector<T>vtTemp;
vtTemp.swap( v );
}
如
vector<int> v ;
nums.push_back(1);
nums.push_back(3);
nums.push_back(2);
nums.push_back(4);
vector<int>().swap(v);
/* 或者v.swap(vector<int>()); */
/*或者{ std::vector<int> tmp = v; v.swap(tmp); }; //加大括号{ }是让tmp退出{ }时自动析构*/
#include<algorithm>中的泛函算法
搜索算法:find() 、search() 、count() 、find_if() 、search_if() 、count_if()
分类排序:sort() 、merge()
删除算法:unique() 、remove()
生成和变异:generate() 、fill() 、transformation() 、copy()
关系算法:equal() 、min() 、max()
iterator失效主要有两种情况:
a.iterator变量已经变成了“悬空指针”,对它进行*,++,--都会引起程序内存操作异常;
b.iterator所指向的变量已经不是你所以为的那个变量了。
6.Stack容器:
堆栈是一种线性表,栈是一种容器适配器,特别为后入先出而设计的一种(LIFO ),那种数据被插入。由于堆栈的底层使用的是其他容器,因此,堆栈可看做是一种适配器,将一种容器转换为另一种容器(堆栈容器)。默认的参数中容器是用deque实现的;被包含的容器要满足提供value_type,size_type,empt,size,push_back,pop_back;可选择的容器有list,deque,vector;要求有最快的平均访问速度,而且大概的容量要求也清楚(比较衡定),那么,使用vector是个不错的选择 要求每次的访问时间平稳,而不在乎平均访问时间时,那么,可以考虑使用list;所以,库默认的deque是个不错的选择,它介于vector和list之间,并且很好的综合了两者的优势。
为了严格遵循堆栈的数据后进先出原则,stack 不提供元素的任何迭代器操作,因此,stack 容器也就不会向外部提供可用的前向或反向迭代器类型。
创建函数:
stack();// 默认构造函数,创建一个空的 stack 对象。
stack(const stack&);// 复制构造函数,用一个 stack 堆栈创建一个新的堆栈。
出入栈函数:
void push(const value_type& x);//入栈,由于 C++ STL 的堆栈函数是不预设大小的,因此,入栈函数就不考虑堆栈空间是否为满,均将元素压入堆栈,从而函数没有标明入栈成功与否的返回值。
void pop();// stack容器的元素出栈函数为 pop 函数,由于函数并没有判断堆栈是否为空,才进行元素的弹出,因此,需要自行判断堆栈是否为空,才可执行 pop 函数。
遍历函数:
value_type& top();//取栈顶元素,原理是先pop后push
属性函数:
size_type size ( ) const;//计算栈对象元素个数
bool empty();//一般需要调用 empty 函数判断是否非空,才作元素出栈和取栈顶元素的操作。
7.queue容器:
与stack 模板类很相似,queue 模板类也需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。
8.deque容器:
deque的实现比较复杂,内部会维护一个map(注意!不是STL中的map容器)即一小块连续的空间,该空间中每个元素都是指针,指向另一段(较大的)区域,这个区域称为缓冲区,缓冲区用来保存deque中的数据。因此deque在随机访问和遍历数据会比vector慢。具体的deque实现可以参考《STL源码剖析》,当然此书中使用的SGI STL与VS2008所使用的PJ STL的实现方法还是有区别的。下面给出了deque的结构图: