Ø vector #include<vector>
1. Vector特点:连续内存空间;具有预留空间,超过预留空间,将移动整个vector.
2. 对中间和开始处进行添加删除元素操作需要移动内存,如果你的元素是结构或是类,那么移动的同时还会进行构造和析构操作,所以性能不高(最好将结构或类的指针放入vector中,而不是结构或类本身,这样可以避免移动时的构造与析构)
补充:
1. resize(int n);
resize()的作用是改变vector中元素的数目。
如果n比当前的vector元素数目要小,vector的容量要缩减到resize的第一个参数大小,既n。并移除那些超出n的元素同时销毁他们。
如果n比当前vector元素数目要大,在vector的末尾扩展需要的元素数目,如果第二个参数val指定了,扩展的新元素初始化为val的副本,否则按类型默认初始化。
注意:如果n大于当前的vector的容量(是容量,并非vector的size),将会引起自动内存分配。所以现有的pointer,references,iterators将会失效。
reserve只是预留出空间,并不真正的创建元素,所以并不会进行初始化。
resize后,修改容器空间,并初始化元素,这时候可以通过operator[]来进行操作
2. v.pop_back();//删除最后一个元素,还有erase,remove
3. v.insert(p,elem);//在指针p指向的位置插入数据elem,返回指向elem位置的指针
4. v.insert(p,n,elem);//在位置p插入n个elem数据,无返回值
Ø map 关键字—值对
特点:会自动按key值排好序;底层实现:红黑树; 经典使用:统计单词出现的个数;
#include<map>
1. 建立map map<int,int> m;// map<string,int>m;//
2. 下标操作:map[int]=int;//map[string]=int;
3. Find: map<string,int>::iterator it=m.find(int);
If(it==m.end())表示没找到
4. 遍历:
for(it = m.begin() ; it != m.end() ; it ++)
{
//输出键值与映照数据
cout << it->first <<" : " << it->second << endl ;
}
//反向遍历:
for(map<int,char>::reverse_iterator rit=m.rbegin();rit!=m.rend();rit++);//
rbegin() 返回一个指向map尾部的逆向迭代器
rend() 返回一个指向map头部的逆向迭代器
5. Insert: m.insert(pair<int,string>(1,"student_one"));
Ø set:只保存关键字的容器:
#include<set> 键值不可重复;用法跟map差不多;底层也是红黑树
举例:
set<int> eg;
eg.insert(1);
eg.insert(2);。。。。。
Ø stack和queue其实是适配器,而不叫容器,因为是对容器的再封装
1. stack #include< stack> 先进后出;深度优先遍历(DFS)用栈来实现(递归就是需要用栈来保存信息)
底层一般用list或deque实现
入栈,如例:s.push(x);
出栈,如例:s.pop();注意,出栈操作只是删除栈顶元素,并不返回该元素。
访问栈顶,如例:s.top()
判断栈空,如例:s.empty(),当栈空时,返回true。
访问栈中的元素个数,如例:s.size()。
遍历:
while(!s.empty())
{
Type t=s.top();
Cout<<t<,endl;
s.pop();
}
2. queue #include< queue> 先进先出;广度优先遍历(BFS)用队列来实现
入队,如例:q.push(x); 将x 接到队列的末端。
出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问队首元素,如例:q.front(),即最早被压入队列的元素。
访问队尾元素,如例:q.back(),即最后被压入队列的元素。
判断队列空,如例:q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:q.size()
遍历:
while(!q.empty())
{
type t=q.front();
cout<<t<<endl;
q.pop();
}
Ø list: list就是双向链表,元素也是在堆中存放,每个元素都是放在一块内存中,它的内存空间可以是不连续的,通过指针来进行数据的访问,这个特点使得它的随即存取变的非常没有效率,因此它没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除和插入
list使用:
list<int>L;
L.push_front(2);// 从前面向L容器中添加数据
L.push_back(3);//后面
//从前向后显示listOne中的数据
for (i = L.begin(); i != L.end(); ++i)
cout << *i << "";
//从后往前
for (ir=listOne.rbegin(); ir!=listOne.rend();ir++) {
cout << *ir << "";
}
L.insert(position,3,9);//表示在position之前插入3个9
Ø deque是一个双端队列(double-ended queue),也是在堆中保存内容的.它的保存形式如下:
[堆1] --> [堆2] -->[堆3] --> ...
每个堆保存好几个元素,然后堆和堆之间有指针指向,看起来像是list和vector的结合品
Ø C++ 11中出现了两种新的关联容器:unordered_set和unordered_map,其内部实现与set和map大有不同,set和map内部实现是基于RB-Tree,而unordered_set和unordered_map内部实现是基于哈希表(hashtable)