STL的基本操作

目录

STL

queue队列

priority_queue优先队列

Map

Multimap

vector集合

stack栈

set

Deque


STL

标准模板库,stl现在是c++的一部分,因此不需要安装额外的库文件。

在C++标准中,STL被组织为下面的13个头文件:<algorithm>、<deque>、<functional>、<iterator>、<array>、<vector>、<list>、<forward_list>、<map>、<unordered_map>、<memory>、<numeric>、<queue>、<set>、<unordered_set>、<stack>和<utility>。

六个部分:STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)。

容器:序列容器:vector、list、deque

关联容器:set、map、multiset、multimap

适配器容器:stack、queue、priority_queue

容器 特性所在头文件
向量vector在常数时间访问和修改任意元素,在序列尾部进行插入和删除时,具有常数时间复杂度。对任意项的插入和删除的时间复杂度与到末尾的距离成正比,尤其对向量头的添加和删除代价比较高。<vector>
双端队列deque基本上与向量相同,不同点是,双端队列的两端插入和删除操作也是常量的时间复杂度。<deque>
表list对任意元素的访问与两端的距离成正比,但对某个位置上插入和删除时间复杂度为常数。<list>
队列queue插入只可以在尾部进行,删除、检索和修改只允许从头部进行。遵循FIFO的原则。<queue>
栈stackLIFO:先进后出原则。只允许在序列头部进行插入、删除、检索和修改操作,时间复杂度为常数。<stack>
集合set内部实现机制是红黑树,每个结点都包含一个元素,结点之间以某种作用于元素对的谓词排列,没有两个不同的元素能够拥有相同的次序,具有快速查找的功能。<set>
多重集合multiset和集合基本相同,但可以支持重复元素。<set>
映射map由(键,值)对组成的集合,以某种作用于键对上的谓词排序。具有快速查找特性。<map>
多重映射multimap支持一键对应多个值的特性,具有快速查找功能。

迭代器:迭代器部分主要由头文件<utility>,<iterator>和<memory>组成。<utility>是一个很小的头文件,它包括了贯穿使用在STL中的几个模板的声明,<iterator>中提供了迭代器使用的许多方法,而对于<memory>的描述则十分的困难,它以不同寻常的方式为容器中的元素分配存储空间,同时也为某些算法执行期间产生的临时对象提供机制,<memory>中的主要部分是模板类allocator,它负责产生所有容器中的默认分配器。

算法:算法部分主要在头文件<algorithm>,<numeric>,<functional>中。<algoritm>是所有STL头文件中最大的一个,它是由一大堆模版函数组成的,可以认为每个函数在很大程度上都是独立的,其中常用到的功能范 围涉及到比较、交换、查找、遍历操作、复制、修改、移除、反转、排序、合并等等。<numeric>体积很小,只包括几个在序列上面进行简单数学运算的模板函数,包括加法和乘法在序列上的一些操作。<functional>中则定义了一些模板类,用以声明函数对象。

适配器是用来修改其他组件接口的STL组件,是带有一个参数的类模板(这个参数是操作的值的数据类型)。STL定义了3种形式的适配器:容器适配器,迭代器适配器,函数适配器。

1)容器适配器:栈(stack)、队列(queue)、优先(priority_queue)。使用容器适配器,stack就可以被实现为基本容器类型(vector,dequeue,list)的适配。可以把stack看作是某种特殊的vctor,deque或者list容器,只是其操作仍然受到stack本身属性的限制。queue和priority_queue与之类似。容器适配器的接口更为简单,只是受限比一般容器要多。

2)迭代器适配器:修改为某些基本容器定义的迭代器的接口的一种STL组件。反向迭代器和插入迭代器都属于迭代器适配器,迭代器适配器扩展了迭代器的功能。

3)函数适配器:通过转换或者修改其他函数对象使其功能得到扩展。这一类适配器有否定器(相当于"非"操作)、绑定器、函数指针适配器。函数对象适配器的作用就是使函数转化为函数对象,或是将多参数的函数对象转化为少参数的函数对象。

 

 

 

queue队列

  • back()返回最后一个元素
  • empty()如果队列空则返回真
  • front()返回第一个元素
  • pop()删除第一个元素
  • push()在末尾加入一个元素
  • size()返回队列中元素的个数

 

 

priority_queue优先队列

  • q.size();//返回q里元素个数
  • q.empty();//返回q是否为空,空则返回1,否则返回0
  • q.push(k);//在q的末尾插入k
  • q.pop();//删掉q的第一个元素
  • q.top();//返回q的第一个元素

自动排序(默认从大到小排序)

  • priority_queue<int,vector<int>,less<int> >q; //从大到小
  • priority_queue<int,vector<int>,greater<int> >q; //从小到大

 

 

Map

Map中的元素是自动按key升序排序,所以不能对map用sort函数

  • 降序:map<int,pair<int,int>,greater<int> >m;
  • 升序:map<int,pair<int,int>,less<int> >m;

C++ Maps是一种关联式容器,包含“关键字/值”对,为了实现快速查找,map内部本身就是按序存储的(比如红黑树)。在我们插入<key, value>键值对时,就会按照key的大小顺序进行存储,其中key的类型必须能够进行 运算,且唯一,默认排序是按照从小到大便利记忆联想到需要支持小于运算。

  1. begin() 返回指向map头部的迭代器
  2. clear() 删除所有元素
  3. count() 返回指定元素出现的次数
  4. empty() 如果map为空则返回true
  5. end() 返回指向map末尾的迭代器
  6. equal_range() 返回特殊条目的迭代器对
  7. erase() 删除一个元素
  8. find() 查找一个元素
  9. get_allocator() 返回map的配置器
  10. insert() 插入元素      enumMap.insert(map<int, CString> :: value_type(2, "Two"))
  11. key_comp() 返回比较元素key的函数
  12. lower_bound() 返回键值>=给定元素的第一个位置
  13. max_size() 返回可以容纳的最大元素个数
  14. rbegin() 返回一个指向map尾部的逆向迭代器
  15. rend() 返回一个指向map头部的逆向迭代器
  16. size() 返回map中元素的个数
  17. swap() 交换两个map
  18. upper_bound() 返回键值>给定元素的第一个位置
  19. value_comp() 返回比较元素value的函数

例子:

//遍历:

 map<int,string>::iterator iter;
 for(iter = m.begin(); iter != m.end(); ++iter)
 {
       cout<<iter->first<<" "<<iter->second<<endl;
   }
 }

//查找:

 map<string,CAgent>::iterator iter=m_AgentClients.find(strAgentName);
 if(iter!=m_AgentClients.end())  {
        //查找成功
 }else {
        //不存在
 }

//删除

 map<string,CAgent>::iterator iter=m.find(pSocket->GetName());
 if(iter!=m.end())
 {
     m.erase(iter);//列表移除
 }

//排序

bool cmp(const pair<int,int> &p1,const pair<int,int> &p2)//要用常数,不然编译错误 
{
	return p1.second<p2.second;
}
int main(void)  
{  
   map<int,int> mp;
   mp[1]=4;
   mp[2]=3;
   mp[3]=2;
   mp[4]=1;
   vector<pair<int,int> > arr;
   for (map<int,int>::iterator it=mp.begin();it!=mp.end();++it)
   {
   	    cout<<it->first<<'\t'<<it->second<<endl;
   	    arr.push_back(make_pair(it->first,it->second));
   }
   sort(arr.begin(),arr.end(),cmp);
   for (vector<pair<int,int> >::iterator it=arr.begin();it!=arr.end();++it)
   {
   	    cout<<it->first<<'\t'<<it->second<<endl;
   }
   return 0;  
}  

 

 

Multimap

头文件:map
 * multimap多重映照容器:容器的数据结构采用红黑树进行管理
 * multimap的所有元素都是pair:第一元素为键值(key),不能修改;第二元素为实值(value),可被修改
 * multimap特性以及用法与map完全相同,唯一的差别在于:
 * 允许重复键值的元素插入容器(使用了RB-Tree的insert_equal函数) 
 * 键值key与元素value的映照关系是多对多的关系
 * 没有定义[]操作运算 

 * 创建multimap对象:
 * 1.multimap<char,int,greater<char> > a;    //元素键值类型为char,映照数据类型为int,键值的比较函数对象为greater<char>
 * 2.multimap(const key_compare& comp)     //指定一个比较函数对象comp来创建map对象
 *  3.multimap(const multisetr&);      //multimap<int,char*> b(a); //此时使用默认的键值比较函数less<int>
 * 4.multimap(first,last);         
 * 5.multimap(first,last,const key_compare& comp);  
 * //Example:
 * pair<const int ,char> p1(1,'a');
 * pair<const int ,char> p2(2,'b');
 * pair<const int ,char> p3(3,'c');
 * pair<const int ,char> p4(4,'d');
 * pair<const int ,char> pairArray[]={p1,p2,p3,p4};
 * multimap<const int,char> m4(pairArray,pairArray+5);
 * multimap<const int,char> m3(m4);
 * multimap<const int,char,greater<const int> > m5(pairArray,pairArray+5,greater<const int>());
 * 元素的插入
 * //typedef pair<const key,T> value_type;
 * pair<iterator,bool> insert(const value_type& v);    
 * iterator insert(iterator pos,const value_type& v);
 * void insert(first,last);
 *
 **************************************************************************************
 *
 * 元素的删除
 * void erase(iterator pos);
 * size_type erase(const key_type& k);     //删除等于键值k的元素
 * void erase(first,last);        //删除[first,last)区间的元素
 * void clear();
 *
 **************************************************************************************
 *
 * 访问与搜索
 *
 * iterator begin();iterator end();     //企图通过迭代器改变元素是不被允许的
 * reverse_iterator rbegin();reverse_iterator rend();
 *
 * iterator find(const key_type& k) const;
 * pair<iterator,iterator> equal_range(const key_type& k) const;//返回的pair对象,
 *                //first为lower_bound(k);大于等于k的第一个元素位置
 *                //second为upper_bound();大于k的第一个元素位置
 *
 * 其它常用函数
 * bool empty() const;
 * size_type size() const;
 * size_type count(const key_type& k) const;   //返回键值等于k的元素个数
 * void swap();
 *
 * iterator lower_bound();iterator upper_bound();pair<iterator,iterator> equal_range();//上界、下届、确定区间

 
#include <map>
#include <string>
#include <iostream>
 
// 基本操作与set类型,牢记map中所有元素都是pair
// 对于自定义类,初学者会觉得比较函数如何构造很麻烦,这个可以参照前面的书写示例
// 但若设置键值为int或char类型,无须构造比较函数
 
struct student{
 char* name;
 int age;
 char* city;
 char* phone;
};
 
int main()
{
     using namespace std;
 
     student s[]={
      {"童进",23,"武汉","XXX"},
      {"老大",23,"武汉","XXX"},
      {"饺子",23,"武汉","XXX"},
      {"王老虎",23,"武汉","XXX"},
      {"周润发",23,"武汉","XXX"},
      {"周星星",23,"武汉","XXX"}
     };
      pair<int,student> p1(4,s[0]);
      pair<int,student> p2(2,s[1]);
      pair<int,student> p3(3,s[2]);
      pair<int,student> p4(4,s[3]);  //键值key与p1相同
      pair<int,student> p5(5,s[4]);
      pair<int,student> p6(6,s[5]);
     multimap<int,student> a;
     a.insert(p1);
     a.insert(p2);
     a.insert(p3);
     a.insert(p4);
     a.insert(p5);
     a.insert(p6);
     typedef multimap<int,student>::iterator int_multimap;
     pair<int_multimap,int_multimap> p = a.equal_range(4);
     int_multimap i = a.find(4);
     cout<<"班上key值为"<< i->first<<"的学生有:"<<a.count(4)<<"名,"<<"   他们是:"<<endl;
     for(int_multimap k = p.first; k != p.second; k++)
     {
        cout<<k->second.name<<endl;
     }
     cout<<"删除重复键值的同学"<<endl;
     a.erase(i);
     cout<<"现在班上总人数为:"<<a.size()<<".   人员如下:"<<endl;
     for(multimap<int,student>::iterator j=a.begin(); j != a.end(); j++)
     {      
          cout<<"The name: "<<j->second.name<<"      "<<"age: "<<j->second.age<<"   "
           <<"city: "<<j->second.city<<"      "<<"phone: "<<j->second.phone<<endl;
     }
 
     return 0;
}

 

 

vector集合

vector作为函数的参数或者返回值时:double Distance(vector<int>&a, vector<int>&b) 其中的“&”绝对不能少.

(1)头文件#include<vector>.

(2)创建vector对象,vector<int> vec;

(3)尾部插入数字:vec.push_back(a);

(4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的。

(5)使用迭代器访问元素.

vector<int>::iterator it;

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

    cout<<*it<<endl;

(6)插入元素: vec.insert(vec.begin()+i,a);在第i+1个元素前面插入a;

(7)删除元素: vec.erase(vec.begin()+2);删除第3个元素

vec.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始

vec.pop_back()删除最后一个元素  或者v.erase(v.end()-1);

(8)向量大小:vec.size();

(9)清空:vec.clear();

(10)二维数组:

vector<vector<Point2f> > points; //定义一个二维数组  两个> >中间必须加一个空格

points[0].size();  //指第一行的列数

(11) 使用reverse将元素翻转:需要头文件#include<algorithm>

reverse(vec.begin(),vec.end());将元素翻转,即逆序排列!

(在vector中,如果一个函数中需要两个迭代器,一般后一个都不包含)

(12)使用sort排序:需要头文件#include<algorithm>

sort(vec.begin(),vec.end());(默认是按升序排列,即从小到大).

可以通过重写排序比较函数按照降序比较,如下:

定义排序比较函数:

bool Comp(const int &a,const int &b)
{
    return a>b;
}
调用时:sort(vec.begin(),vec.end(),Comp),这样就降序排序。 

vector的几种初始化及赋值方式:

(1)不带参数的构造函数初始化

//初始化一个size为0的vector
vector<int> abc;

(2)带参数的构造函数初始化

//初始化size,但每个元素值为默认值
vector<int> abc(10);    //初始化了10个默认值为0的元素
//初始化size,并且设置初始值
vector<int> cde(10,1);    //初始化了10个值为1的元素

(3)通过数组地址初始化

int a[5] = {1,2,3,4,5};
//通过数组a的地址初始化,注意地址是从0到5(左闭右开区间)
vector<int> b(a, a+5);

(4)通过同类型的vector初始化

vector<int> a(5,1);
//通过a初始化
vector<int> b(a);

(5)通过insert初始化

//insert初始化方式将同类型的迭代器对应的始末区间(左闭右开区间)内的值插入到vector中
vector<int> a(6,6);
vecot<int> b;
//将a[0]~a[2]插入到b中,b.size()由0变为3
b.insert(b.begin(), a.begin(), a.begin() + 3);

此外,insert还可以插入m个值为n的元素

//在b开始位置处插入6个6
b.insert(b.begin(), 6, 6);

(6)通过copy函数赋值

vector<int> a(5,1);
int a1[5] = {2,2,2,2,2};
vector<int> b(10);

/*将a中元素全部拷贝到b开始的位置中,注意拷贝的区间为a.begin() ~ a.end()的左闭右开的区间*/
copy(a.begin(), a.end(), b.begin());

//拷贝区间也可以是数组地址构成的区间
copy(a1, a1+5, b.begin() + 5);

 

 

 

stack栈

1.入栈:如s.push(x);

2.出栈 : 如 s.pop().   注意:出栈操作只是删除栈顶的元素,不返回该元素。

3.访问栈顶:如s.top();

4.判断栈空:如s.empty().当栈空时返回true。

5.访问栈中的元素个数,如s.size()。

 

 

set

set的特性是,所有元素都会根据元素的键值自动排序,set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值。set不允许两个元素有相同的键值

set的各成员函数列表如下:

1. begin()--返回指向第一个元素的迭代器

2. clear()--清除所有元素

3. count()--返回某个值元素的个数

4. empty()--如果集合为空,返回true

5. end()--返回指向最后一个元素的迭代器

6. equal_range()--返回集合中与给定值相等的上下限的两个迭代器

7. erase()--删除集合中的元素

8. find()--返回一个指向被查找到元素的迭代器

9. get_allocator()--返回集合的分配器

10. insert()--在集合中插入元素

11. lower_bound()--返回指向大于(或等于)某值的第一个元素的迭代器

12. key_comp()--返回一个用于元素间值比较的函数

13. max_size()--返回集合能容纳的元素的最大限值

14. rbegin()--返回指向集合中最后一个元素的反向迭代器

15. rend()--返回指向集合中第一个元素的反向迭代器

16. size()--集合中元素的数目

17. swap()--交换两个集合变量

18. upper_bound()--返回大于某个值元素的迭代器

19. value_comp()--返回一个用于比较元素间的值的函数

set<int>::iterator iter;
    iter = team.find(in);
    if(iter != team.end()) {
        //找到
    } else {
        //没找到
    }


 

Deque

deque.push_back(elem);  //在容器尾部添加一个数据
deque.push_front(elem); //在容器头部插入一个数据
deque.pop_back();           //删除容器最后一个数据
deque.pop_front();      //删除容器第一个数据
eque.at(idx);  //返回索引idx所指的数据,如果idx越界,抛出out_of_range。
deque[idx];  //返回索引idx所指的数据,如果idx越界,不抛出异常,直接出错。
deque.front();   //返回第一个数据。
deque.back();  //返回最后一个数据
deque.begin();  //返回容器中第一个元素的迭代器。
deque.end();  //返回容器中最后一个元素之后的迭代器。
deque.rbegin();  //返回容器中倒数第一个元素的迭代器。
deque.rend();   //返回容器中倒数最后一个元素之后的迭代器。
deque(beg,end);    //构造函数将[beg, end)区间中的元素拷贝给本身。注意该区间是左闭右开的区间。
deque(n,elem);   //构造函数将n个elem拷贝给本身。
deque(const deque  &deq);  //拷贝构造函数。
deque.assign(beg,end);    //将[beg, end)区间中的数据拷贝赋值给本身。注意该区间是左闭右开的区间。
deque.assign(n,elem);  //将n个elem拷贝赋值给本身。
deque& operator=(const deque &deq); //重载等号操作符 
deque.swap(deq);  // 将vec与本身的元素互换
deque.size();      //返回容器中元素的个数
deque.empty();     //判断容器是否为空
deque.resize(num);   //重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem);  //重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.insert(pos,elem);   //在pos位置插入一个elem元素的拷贝,返回新数据的位置。
deque.insert(pos,n,elem);   //在pos位置插入n个elem数据,无返回值。
deque.insert(pos,beg,end);   //在pos位置插入[beg,end)区间的数据,无返回值。

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值