Cristiano的STL总结

迭代器
1、迭代器的简单概念
迭代器(iterator)是一个对象,常用它来遍历容器,即在容器中实现“取得下一个元素”的操作。
迭代器的操作类似于指针,但它是基于模板的“功能更强大、更智能、更安全的指针”,用于指示容器中的元素位置,通过迭代器能够遍历容器中的每个元素。
2、迭代器的操作
迭代器提供的基本操作包括:

  • 在容器中的特定位置定位迭代器。
  • 在迭代器指示位置检查是否存在对象。
  • 获取存储在迭代器指示位置的对象值。
  • 改变迭代器指示位置的对象值。
  • 在迭代器指示位置插入新对象。
  • 将迭代器移到容器中的下一个位置。
    3、迭代器主要提供的方法
operator *		返回当前位置上的元素值  如: *iter
operator++ 		将迭代器前进到下一个元素位置
operator--		将迭代器后退到前一个元素位置
operator==operator!= 	
operator=		为迭代器赋值
begin()	指向容器起点(即第一个元素)位置
end()		指向容器的结束点
rbegin()	指向按反向顺序的第一个元素位置
rend()	指向按反向顺序的最后一个元素后的位置

容器
一、C++容器的概念及类型
容器(container)是用来存储其他对象的对象,它是用模板技术实现的。 STL的容器常被分为顺序容器、关联容器和容器适配器三类。
C++提供的顺序类型容器有 向量(vector)、链表(list)、双端队列(deque)
关联容器主要包括 集合(set)、多重集合(multiset),map,multimap
容器适配器主要指 堆栈(stack)和队列(queue)
在这里插入图片描述
在这里插入图片描述
顺序和关联容器共同支持的成员函数

begin();
end();
rbegin();
rend();
erase();
clear();

二、stack容器
头文件: #include <stack
使用:

stack<int> s;
stack<int, vector<int>> stk;  //覆盖基础容器类型,使用vector实现stk
s.empty();  //判断stack是否为空,为空返回true,否则返回false
s.size();   //返回stack中元素的个数
s.pop();    //删除栈顶元素,但不返回其值
s.top();    //返回栈顶元素的值,但不删除此元素
s.push(item); 

三、queue容器
头文件: #include <queue
1、队列 queue
使用方法:

queue<int> q; 
priority_queue<int> q;
q.empty();  //判断队列是否为空
q.size();   //返回队列长度
q.push(item);   //对于queue,在队尾压入一个新元素
               //对于priority_queue,在基于优先级的适当位置插入新元素
q.pop();        
 //queue only:
q.front();  //返回队首元素的值,但不删除该元素
q.back();   //返回队尾元素的值,但不删除该元素
 
//priority_queue only:
q.top();    //返回具有最高优先级的元素值,但不删除该元素

2、优先队列 priority_queue
优先队列定义:具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的
定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆

  //对于基础类型 默认是大顶堆
    priority_queue<int> a; 
    //等同于 priority_queue<int, vector<int>, less<int> > a;
    //末尾位置一定要有空格,不然成了右移运算符↓
    priority_queue<int, vector<int>, greater<int> > c;  //这样就是小顶堆

四、deque对列
定义:双端队列是一种随机访问的数据类型,提供了在序列两端快速插入和删除操作的功能,它可以在需要的时候改变自身大小,完成了标准的C++数据结构中队列的所有功能。
声明deque容器:

#include<deque>  // 头文件
deque<int> deq;   //声明一个元素类型为int型的双端队列que
deque<type> deq;  // 声明一个元素类型为type的双端队列que
deque<type> deq(size);  // 声明一个类型为type、含有size个默认值初始化元素的的双端队列que
deque<type> deq(size, value);  // 声明一个元素类型为type、含有size个value元素的双端队列que
deque<type> deq(mydeque);  // deq是mydeque的一个副本
deque<type> deq(first, last);  // 使用迭代器first、last范围内的元素初始化de

deque常见函数

deq[ ]:用来访问双向队列中单个的元素。
deq.front():返回第一个元素的引用。
deq.back():返回最后一个元素的引用。
deq.push_front(x):把元素x插入到双向队列的头部。
deq.pop_front():弹出双向队列的第一个元素。
deq.push_back(x):把元素x插入到双向队列的尾部。
deq.pop_back():弹出双向队列的最后一个元素。

五、vector容器
定义:vector是向量容器,它具有存储管理的功能,在插入或删除数据时,vector能够自动扩展和压缩其大小。可以像数组一样使用vector,通过运算符[ ]访问其元素,但它比数组更灵活,当添加数据时,vector的大小能够自动增加以容纳新的元素
构造函数

vector():创建一个空vector
vector(int nSize):创建一个vector,元素个数为nSizew
vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t
vector(const vector&):复制构造函数
vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中

增加函数

void push_back(const T& x):向量尾部增加一个元素X
iterator insert(iterator it,const T& x):向量中迭代器指向元素前增加一个元素x
iterator insert(iterator it,int n,const T& x):向量中迭代器指向元素前增加n个相同的元素x
iterator insert(iterator it,const_iterator first,const_iterator last):向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据0

删除函数

iterator erase(iterator it):删除向量中迭代器指向元素
iterator erase(iterator first,iterator last):删除向量中[first,last)中元素
void pop_back():删除向量中最后一个元素
void clear():清空向量中所有元素

遍历函数

reference at(int pos):返回pos位置元素的引用
reference front():返回首元素的引用
reference back():返回尾元素的引用
iterator begin():返回向量头指针,指向第一个元素
iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置
reverse_iterator rbegin():反向迭代器,指向最后一个元素
reverse_iterator rend():反向迭代器,指向第一个元素之前的位置
display():直接遍历整个vector向量

判断函数

bool empty() const:判断向量是否为空,若为空,则向量中无元素

大小函数

int size() const:返回向量中元素的个数
void resize():重置向量的大小
int capacity() const:返回当前向量张红所能容纳的最大元素值
int max_size() const:返回最大可允许的vector元素数量值

其他函数

void swap(vector&):交换两个同类型向量的数据
void assign(int n,const T& x):设置向量中第n个元素的值为x
void assign(const_iterator first,const_iterator last):向量中[first,last)中元素设置成当前向量元素

二维数组的定义方法

int N=5, M=6; 
vector<vector<int> > obj(N); //定义二维动态数组大小5行
for(int i =0; i< obj.size(); i++)//动态二维数组为5行6列,值全为0 
   obj[i].resize(M);  

int N=5, M=6; 
vector<vector<int> > obj(N, vector<int>(M)); //定义二维动态数组5行6列
vector<int> in[1200];//该定义方式表示数组的长度是随意的,宽度均为1200	

六、List容器
List是stl实现的双向链表,与向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢。使用时需要添加头文件#include <list
list定义和初始化

list<int>lst1;          //创建空list
list<int> lst2(5);       //创建含有5个元素的list
list<int>lst3(3,2);  //创建含有3个元素的list,每个元素初始化为2 
list<int>lst4(lst2);    //使用lst2初始化lst4
list<int>lst5(lst2.begin(),lst2.end());  //同lst4

函数:

Lst1.assign() 给list赋值 
Lst1.back() 返回最后一个元素 
Lst1.begin() 返回指向第一个元素的迭代器 
Lst1.clear() 删除所有元素 
Lst1.empty() 如果list是空的则返回true 
Lst1.end() 返回末尾的迭代器 
Lst1.erase() 删除一个元素 
Lst1.front() 返回第一个元素 
Lst1.get_allocator() 返回list的配置器 
Lst1.insert() 插入一个元素到list中 
Lst1.max_size() 返回list能容纳的最大元素数量 
Lst1.merge() 合并两个list 

Lst1.pop_back() 删除最后一个元素 
Lst1.pop_front() 删除第一个元素 
Lst1.push_back() 在list的末尾添加一个元素 
Lst1.push_front() 在list的头部添加一个元素 

Lst1.rbegin() 返回指向第一个元素的逆向迭代器 
Lst1.remove() 从list删除元素 
Lst1.remove_if() 按指定条件删除元素 
Lst1.rend() 指向list末尾的逆向迭代器 
Lst1.resize() 改变list的大小 
Lst1.reverse() 把list的元素倒转 

Lst1.size() 返回list中的元素个数 
Lst1.sort() 给list排序 
Lst1.splice() 合并两个list 
Lst1.swap() 交换两个list 
Lst1.unique() 删除list中相邻重复的元素

七、map/multimap
map和multimap都需要#include,唯一的不同是,map的键值key不可重复,而multimap可以,也正是由于这种区别,map支持[ ]运算符,multimap不支持[ ]运算符。在用法上没什么区别。

C++中map提供的是一种键值对容器,里面的数据都是成对出现的,每一对中的第一个值称之为关键字(key),每个关键字只能在map中出现一次;第二个称之为该关键字的对应值。
基本操作函数

     begin()         返回指向map头部的迭代器
     clear()        删除所有元素
     count()         返回指定元素出现的次数
     empty()         如果map为空则返回true
     end()           返回指向map末尾的迭代器
     equal_range()   返回特殊条目的迭代器对
     erase()         删除一个元素
     find()          查找一个元素
     get_allocator() 返回map的配置器
     insert()        插入元素
     key_comp()      返回比较元素key的函数
     lower_bound()   返回键值>=给定元素的第一个位置
     max_size()      返回可以容纳的最大元素个数
     rbegin()        返回一个指向map尾部的逆向迭代器
     rend()          返回一个指向map头部的逆向迭代器
     size()          返回map中元素的个数
     swap()           交换两个map
     upper_bound()    返回键值>给定元素的第一个位置
     value_comp()     返回比较元素value的函数

插入操作

int main(){
    
    
//数据的插入--第一种:用insert函数插入pair数据    
    map<int, string> mapStudent;  
    mapStudent.insert(pair<int, string>(1, "student_one"));  
    mapStudent.insert(pair<int, string>(2, "student_two"));  
    mapStudent.insert(pair<int, string>(3, "student_three"));  
    map<int, string>::iterator iter;  
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  
       cout<<iter->first<<' '<<iter->second<<endl;  

//第二种:用insert函数插入value_type数据,下面举例说明  
   map<int, string> mapStudent;    
    mapStudent.insert(map<int, string>::value_type (1, "student_one"));    
    mapStudent.insert(map<int, string>::value_type (2, "student_two"));    
    mapStudent.insert(map<int, string>::value_type (3, "student_three"));    
    map<int, string>::iterator iter;    
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)  
         cout<<iter->first<<' '<<iter->second<<endl;   
 
 //第三种:用数组方式插入数据,下面举例说明  
   map<int, string> mapStudent;    
    mapStudent[1] = "student_one";   
    mapStudent[2] = "student_two";    
    mapStudent[3] = "student_three";    
    map<int, string>::iterator iter;    
    for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)    
        cout<<iter->first<<' '<<iter->second<<endl;    
}
map数组与普通数组的区别:
(1)map不需要提前分配存储空间,而数组需要
(2)数组可能会发生越界的情况,但map不会
(3)map对应的键值不需要初始化,已经自动初始化完毕

以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的 插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是插入数据不了的,但是用数组方式就不同了,它可以覆盖以前该关键字对应的值
补充:插入函数insert一共有四个重载函数

// 插入单个键值对,并返回插入位置和成功标志,插入位置已经存在值时,插入失败
pair<iterator,bool> insert (const value_type& val);
//在指定位置插入,在不同位置插入效率是不一样的,因为涉及到重排
iterator insert (const_iterator position, const value_type& val);
// 插入多个
void insert (InputIterator first, InputIterator last);
//c++11开始支持,使用列表插入多个   
void insert (initializer_list<value_type> il);

//运用实例:
std::map<char, int> mymap;
    // 插入单个值
    mymap.insert(std::pair<char, int>('a', 100));
    mymap.insert(std::pair<char, int>('z', 200));
    //返回插入位置以及是否插入成功
    std::pair<std::map<char, int>::iterator, bool> ret;
    ret = mymap.insert(std::pair<char, int>('z', 500));
    if (ret.second == false) {
    
    
        std::cout << "element 'z' already existed";
        std::cout << " with a value of " << ret.first->second << '\n';
    }
    //指定位置插入
    std::map<char, int>::iterator it = mymap.begin();
    mymap.insert(it, std::pair<char, int>('b', 300));  //效率更高
    mymap.insert(it, std::pair<char, int>('c', 400));  //效率非最高
    //范围多值插入
    std::map<char, int> anothermap;
    anothermap.insert(mymap.begin(), mymap.find('c'));
    // 列表形式插入
    anothermap.insert({
    
     {
    
     'd', 100 }, {
    
    'e', 200} });a

查找

// 关键字查询,找到则返回指向该关键字的迭代器,否则返回指向end的迭代器
// 根据map的类型,返回的迭代器为 iterator 或者 const_iterator
iterator find (const key_type& k);
const_iterator find (const key_type& k) const;

删除

// 删除迭代器指向位置的键值对,并返回一个指向下一元素的迭代器
iterator erase( iterator pos )
// 删除一定范围内的元素,并返回一个指向下一元素的迭代器
iterator erase( const_iterator first, const_iterator last );
// 根据Key来进行删除, 返回删除的元素数量,在map里结果非0即1
size_t erase( const key_type& key );
// 清空map,清空后的size为0
void clear();

八、set/multiset
(1)std::set 是关联容器,含有 Key 类型对象的已排序集。用比较函数compare进行排序。搜索、移除和插入拥有对数复杂度。 set 通常以红黑树实现。
(2)set容器内的元素会被自动排序,set与map不同,set中的元素即是键值又是实值,set **不允许两个元素有相同的键值 **。不能通过set的迭代器去修改set元素,原因是修改元素会破坏set组织。当对容器中的元素进行插入或者删除时,操作之前的所有迭代器在操作之后依然有效。
(3)由于set元素是排好序的,且默认为升序,因此当set集合中的元素为结构体或自定义类时,该结构体或自定义类必须实现运算符‘<’的重载。
(4)multiset特性及用法和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()--返回一个用于比较元素间的值的函数

使用实例:

#include<iostream>
#include<string>
#include<set>
using namespace std;
void main(){
    
    
		int a1[]={
    
    -2,0,30,12,6,7,12,10,9,10};
		set<int,greater<int> >set1(a1,a1+7);	
		set<int,greater<int> >::iterator p1;
		set1.insert(12);
	  	set1.insert(12);		//向集合插入元素
		set1.insert(4);    
		for(p1=set1.begin();p1!=set1.end();p1++)
			cout<<*p1<<"  "; //输出集合中的内容,它是从大到小的
		cout<<endl;                         
		string a2[]={
    
    "杜明","王为","张清山","李大海","黄明浩",
		               "刘一","张三","林浦海","王小二","张清山"};
		//定义字符串的multiset集合,默认排序从小到大
		multiset<string>set2(a2,a2+10);   
		multiset<string>::iterator p2;
		set2.insert("杜明");  set2.insert("李则");
		for(p2=set2.begin();p2!=set2.end();p2++)
			cout<<*p2<<"  ";           	//输出集合内容
		cout<<endl;
		string sname;
		cout<<"输入要查找的姓名:";
		cin>>sname;                   		//输入要在集合中查找的姓名
		p2=set2.begin();
		bool s=false;                  	//s用于判定找到姓名与否
		while(p2!=set2.end()){
    
    
			if(sname==*p2) {
    
              	//如果找到就输出姓名
				cout<<*p2<<endl;
				s=true;
			}
			p2++;
		}
    if(!s)
cout<<sname<<"不在集合中!"<<endl;	//如果没有找到就给出提示
}

猜你喜欢

转载自blog.csdn.net/Cristiano_san/article/details/109154167