STL总结之vector、deque、list

来源:互联网 发布:知乎 古龙经典片段 编辑:程序博客网 时间:2024/04/29 19:17

一、vector

#include <vector>

vector支持随机存取,在末端附加或删除元素时,vector性能相当好,若在前端或中部安插或删除
元素时,性能差,因为操作点后的每一个元素都要移到另一个位置,而每一次移动都得调用赋值操作符。
vector优异性能的秘诀之一是,配置比其所容纳的元素所需更多的内存。capacity()返回vector实际
能够容纳的元素数量。如果超越这个数量,vector就有必要重新配置内部存储器。
vector的容量之所以很重要,因为:
1)一旦内存重新配置,和vector元素相关的所有引用、指针、迭代器都会失效。
2)内存重新配置很耗时间。
保留适当容量的方式:
1)std::vector<int>v;
 v.reserve(100);
2)std::vector<T> v(5); //必须提供默认构造函数
vector不能使用reserve来缩减容量,若参数比当前容量还小,不会引发任何反应。即使删除元素,其
引用、指针、迭代器也会继续有效,然而安插却可能使之失效(重新配置空间)。
有一个间接缩减容量的窍门:
template <class T>
void shrinkCapacity(std::vector<T>& v){
std::vector<T> temp(v); //v的容量大于等于swap
v.swap(temp); //会使所有指针、引用、迭代器失效
}
vector的操作函数:
构造函数和析构函数:
vector<Elem> c;
vector<Elem> c1(c2);
vector<Elem> c(n);
vector<Elem> c(n,elem);
vector<Elem> c(beg,end);
c.~vector<Elem>()
赋值操作符:
c1 = c2
c.assign(n,elem)
c.assign(beg,end);
c1.swap(c2);
swap(c1,c2);
非变动操作:
c.size(); //当前元素数量
c.empty();
c.max_size(); //可容纳的元素最大数量
capacity(); //重新分配空间前所能容纳的元素最大数量
> < == != <= >=
元素存取:
c.at(index) //抛出异常
c[index]
c.front()
c.back()
迭代器相关:
c.begin()
c.end()
c.rbegin()
c.rend()
vector迭代器持续有效,除非:1)在一个较小索引位置安插或移除元素
2)容量变化引起内存重新分配
安插移除元素:
c.insert(pos,elem); //返回新元素位置
c.insert(pos,n,elem); //void
c.insert(pos,beg,end); // void
c.push_back(elem); //尾部添加
c.pop_back(); //移除
c.erase(beg,end); // 返回下一元素位置
c.erase(pos); // 返回下一元素位置
c.resize(num); //若size变大,多出元素用default
c.resize(num,elem);
c.clear();
移除与某值相等的元素:
std::vector<Elem> coll;
...
coll.erase(remove(coll.begin(),coll.end(),val),coll.end());
移除与某值相等的第一个元素:
std::vector<Elem> coll; ...
std::vector<Elem>::iterator pos;
pos = find(coll.begin(),coll.end(),val);
if(pos != coll.end()){
coll.erase(pos);
}
vector内的元素一定分布于连续空间中,因此可作为一般数组使用
std::vector<char> v;
v.resize(41);
strcpy(&v[0],"hello,world");//注意容量:C-String最后有'/0'
不可将vector迭代器当做第一元素的地址来传递,vector迭代器是由实作版本定义的,也许不是个一般指针:
printf("%s\n",v.begin()); //error
printf("%s\n",&v[0]); //ok
vector运用实例:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
void main(){
vector<string> sentence;
sentence.reserve(5);
sentence.push_back("hello,");
sentence.push_back("how");
sentence.push_back("are");
sentence.push_back("you");
sentence.push_back("?");
copy(sentence.begin(),sentence.end(),ostream_iterator<string>(cout," "));
cout<<endl;
cout<<" max_size(): "<<sentence.max_size()<<endl;
cout<<" size(): "<<sentence.size()<<endl;
cout<<" capacity(): "<<sentence.capacity()<<endl;
swap(sentence[1],sentence[3]);
sentence.insert(find(sentence.begin(),sentence.end(),"?"),"always");
sentence.back() = "!";
copy(sentence.begin(),sentence.end(),ostream_iterator<string>(cout," "));
cout<<endl;
cout<<" max_size(): "<<sentence.max_size()<<endl;
cout<<" size(): "<<sentence.size()<<endl;
cout<<" capacity(): "<<sentence.capacity()<<endl;

} //max_size()和capacity()由实作版本决定,容量不足时,容量扩充一倍

运行结果:


C++标准程序库专门为bool型的vector设计了一个特殊版本:vector<bool>

vector<bool>大小可动态改变,当需要静态大小的bitfield时,应当使用bitset.

vector<bool>的特殊操作:

c.flip() //将所有的bool元素取反值,即求补码

m[idx].flip()

m[idx] = val

m[idx1] = m[idx2];

二、deque

#include <deque>

deque通常作为一组独立区块,第一区块朝某方向扩展,最后一个区块朝另一个方向扩展。

deque的能力(与vector相比):

两端都能快速安插移除元素,除了头尾两端,在其他地方插删元素都会导致指向deque元素的任何引用、指针、迭代器

失效。不过,deque的内存重分配优于vector,不需复制所有元素。也因此,在存取元素时,内部结构会多一个间接过程,动作

会稍慢;在不同区块中跳转,必须是特殊的智能指针,非一般指针;在对内存区块有限制的内存中,deque可内含更多元素,因为

它使用不止一块内存。deque的内存区块不再被使用时,会被释放,deque的内存大小是可缩减的。

deque 的操作函数跟vector差不多,有以下不同:

deque不提供容量操作:capacity()和reserve()

deque可在直接头部安插删除元素 :push_front(),pop_front()

deque的运用实例:

#include <iostream>

#include <deque>

#include <string>

#include <algorithm>

using namespace std;

void main(){

deque<string> coll;

coll.assign(3,string("string"));

coll.push_back("last string");

coll.push_front("first string");

copy(coll.begin(),coll.end(),ostream_iterator<string>(cout,"\n"));

cout<<endl;

coll.pop_front();

coll.pop_back();

for(int i = 1;i<coll.size(); ++i){

coll[i] = "another " + coll[i];

}

coll.resize(4,"resized string");

coll(coll.begin(),coll.end(),ostream_iterator<string>(cout,"\n"));

}

三、list

#include <list>

list不支持随机存取,在任何位置上安插移除元素都非常快,安插移除并不会造成指向其他元素的

指针,引用,迭代器失效。list对于异常的处理方式:要么成功,要么什么都不发生

list与vector、deque的不同:

1)不支持随机存取,不提供[]下标操作符、at()

2)不提供也无必要提供容量、空间重新分配等操作函数,每个元素都有自己的内存

3)list提供了不少成员函数专门用于移动元素,较之同名的STL算法,它们更快,只需调整指针即可

list的安插、移除操作函数:

c.push_front(elem)

c.pop_front()

c.remove(val) //移除所有值为val的元素

c.remove_if(op) 

其他和vector相同

list的特殊变动性操作:

c.unique() //若存在若干相邻且数值相等的元素,就移除重复元素,只留下一个

c.unique(op)

c1.splice(pos,c2); //将c2的所有元素转移到c1内,pos前

c1.splice(pos,c2,c2pos);

c1.splice(pos,c2,c2beg,c2end);

c.sort();// <

c.sort(op);

c1.merge(c2); // c1、c2都含已序元素,将c2的全部元素转移到c1,合并后仍有序

c1.merge(c2,op);

c1.reverse();

list运用实例:

#include <iostream>

#include <list>

#include <algorithm>

using namespace std;

void printLists(const list<int>& l1,const list<int>& l2){

cout<<"list: ";

copy(l1.begin(),l1.end(),ostream_iterator<int>(cout," "));

cout<<endl;

copy(l2.begin(),l2.end(),ostream_iterator<int>(cout," "));

cout<<endl;

}

void main(){

list<int> list1,list2;

for(int i=0;i<6;++i){

list1.push_back(i);

list2.push_front(i);

}

printLists(list1,list2);

list2.splice(find(list2.begin(),list2.end(),3),list1);

printLists(list1,list2);

list2.splice(list2.end(),list2,list2.begin());

printLists(list1,list2);

list2.sort();

list1 = list2;

list2.unique();

printLists(list1,list2);

list1.merge(list2);

printLists(list1,list2);

}






0 0
原创粉丝点击