C++ STL容器

在C++的学习中,STL容器和相关的底层数据结构、涉及的算法,是一个难点。这里我们省略了一些具体的操作和代码实现,只对其做一个大致的总结:

一、STL容器可以分为:

序列式容器:如,vector、list、deque、stack、queue、heap、priority_queue、slist。

关联式容器:如,set、map、multiset、multimap、hash_table、hash_set、hash_map、hash_multiset、hash_multimap。

二、不同容器的底层实现:

1、vector:数组 ,支持快速随机访问。     

2、list:双向链表,支持快速增删。

3、deque:一个中央控制器和多个缓冲区,支持首尾(中间不能)快速增删,也支持随机访问。

4、stack:list或deque实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时。

5、queue:底层一般用list或deque实现,封闭头部即可,不用vector的原因应该是容量大小有限制,扩容耗时(stack和   queue其实是适配器,而不叫容器,因为是对容器的再封装)。

6、priority_queue:底层数据结构一般为vector为底层容器,堆heap为处理规则来管理底层容器实现

7、set:为红黑树,有序,不重复

8、multiset:红黑树,有序,可重复

9、map:红黑树,有序,不重复

10、multimap:红黑树,有序,可重复   

11、hash_set:hash表,无序,不重复

12、hash_multiset:hash表,无序,可重复 13、hash_map:hash表,无序,不重复 14、hash_multimap:hash表,无序,可重复 

三、相关的知识点和操作:

1、 vector和数组的区别:

a、数组存放在栈区,vector存放在堆区,由STL库中程序负责内存分配、释放;

b、vector可以看成动态数组,可以通过相应函数改变大小;

c、数组不能直接把数组拷贝或b用一个数组给另一个数组赋值,vector可以;

d、vector扩容需要大量时间,所以数组效率更高。

2、vector的基本操作:

vector的基本操作有,加头文件#include<vector>、创建vector<int> vec、尾部插入vec.push_back()、指定位置插入vec.insert(vec.begin()+i,a)(在i+1个元素前插入a)、访问cout<<vec[0]<<endl等等。特别的,使用迭代器访问的方式为:vector<int>::iterator it;

for(it=vec.begin();it!=vec.end();it++)

cout<<*it<<endl;

3、list:将元素按顺序储存在链表中。与vector相比, 它允许快速的插入和删除,但是随机访问却比较慢。list的基本操作有:

头文件:#include<list>、声明:list<int> a、插入push_back()和push_front()、指定位置插入:insert()、删除:pop_back()和pop_front()、逆置reverse()、交换两个链表:swap()、替换:assign()等等。

4、deque:也叫做双端队列。     

deque特点:    

 1)支持随即存取,也就是[]操作符,

2)支持两端操作,push(pop)-back(front),在两端操作上与list效率差不多

deque的常用函数:

使用头文件#include <deque>、创建deque<int> d、尾部插入用push_back()、头部插入用push_front()、其它位置插入用insert(&pos, elem)、尾部删除用pop_back()、头部删除用pop_front()、任意迭代位置或迭代区间上的元素删除:erase(&pos)/erase(&first,&last)、删除所有元素用clear()、特别的,关于迭代器的使用:

deque<int>::iterator iter = d.begin();

for (;iter != d.end(); iter ++)

{

cout<<"d["<<iter-d.begin()<<"] = "<<(*iter)<<", ";

}    

关于迭代器指针的使用:

deque<int>::iterator *pIter = new deque<int>::iterator;

if ( NULL == pIter )

{

return ;

}

for (*pIter = d.begin(); *pIter != d.end(); (*pIter)++)

{    

cout<<"d["<<*pIter - d.begin() <<"]="<<**pIter<<", ";

}

if (NULL != pIter)

{    

delete pIter;    

pIter = NULL;

}  

5、vector、list、deque的逻辑结构、物理结构:

vector维护的是一个连续的线性空间,和数组是一样的。所以不论其元素为何种型别,普通指针就可以作为vector的迭代器,但vector是个单向开口的连续线性空间, 所以从尾端插入元素效率较高,而如果从头部插入,则效率奇差;lis是一个环状双向链表; deque 是一种双向开口的连续线性空间,可以从两端插入,效率也很高。deque在实现上主要有两点:a、由一段一段的定量连续空间构成,第一个区块朝某个方向扩展,最后一个区块朝相反方向扩展;b、管理这些分段的定量连续空间,维护其整体连续的假象,并提供随机存取的接口。

6、stack、queue、priority_queue实际为适配器,适配就是改变接口而不改变底层实现方式,其中stack是一个线性表,插入和删除只在表的一端进行,为了严格遵循堆栈的数据后进先出原则,stack 不提供元素的任何迭代器操作。

stack的基本操作有:

声明一个stack: stack<int> s1或者 stack<string> s2。

stack中的操作stack<int> s;s.push(x)      //无返回值,将元素x压栈

s.pop();       //退栈,无返回值

s.top();        //取栈顶元素,返回栈顶元素

s.empty();     //判断栈是否为空,如果是空,返回1,否则返回0

s.size();      //返回栈中元素的个数

在栈中没有提供清空操作的函数,但是可以间接地实现清空栈,

while(!s.empty())  

{   

s.pop();  

}

7、queue和deque的区别:

deque是双端队列,支持push_front、pop_front、push_back、pop_back等几种操作的。queue是容器适配器。

8、priority_queue的基本操作:头文件:#include<queue>、定义:priority_queue<int> p;、优先输出大数据:priority_queue<int> p;优先输 出小数据:priority_queue<int, vector<int>, greater<int> > p;  等等。

9、set:能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序,但是set中数元素的值不能直接被改变。其底层结构为红黑树,其统计性能要好于一般平衡二叉树。mutiset和set最大的区别就是,它可以插入重复的元素,如果删除的话,相同的也一起删除了;如果查找的话,返回该元素的迭代器的位置,若有相同,返回第一个元素的地址;其他使用和set基本类似。

set的基本操作有:返回set容器的第一个元素:begin()、返回set容器的最后一个元素:end()、删除set容器中的所有的元素:clear()、判断set容器是否为空:empty() 、返回set容器可能包含的元素最大个数:max_size() 、返回当前set容器中的元素个数:size()、返回的值和end()(begin())相同:rend()(rbegin())。

10、map:提供一对一的数据处理能力,使用关键值Key来唯一标识每一个成员,键使用比较函数Compare比较来进行排序。搜索,删除和插入操作具有对数复杂性。multimap相对map来说能够允许重复值的存在。map的基本操作:创建:map<int, string> map2;  添加:map2.insert(pair<int, string>(11, "test11")); 删除:

while (!map2.empty())

{

map<int, string>::iterator it = map2.begin();

map2.erase(it); //删除

}

等等。

11、hash_map和map的应用场景:

使用hash_map还是map需要考虑三个要素:查找速度, 数据量, 内存使用。hash_map的查找级别是常数,map是对数。但是,使用 hash_map有hash函数的耗时,并且hash_map是以空间换时间,需要消耗大量内存。hash_map的函数和map的函数差不多。除了hash_map之外,还有hash_set, hash_multimap, has_multiset, 这些容器使用起来和set, multimap, multiset的区别与hash_map和map的区别一样。

四、相关算法 前面提到的容器中,其底层涉及的算法主要的有:heap相关的算法、红黑树、hash散列,其相关内容将在STL容器的算法篇给出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值