C++中STL容器总结

1、容器分类

STL中通常将容器分为三类:顺序容器关联容器容器适配器
1、顺序容器

是一种各元素之间有顺序关系的线性表,是一种线性结构的可序群集。顺序性容器中的每个元素均有固定的位置,除非用删除或插入的操作改变这个位置。顺序容器的元素排列次序与元素值无关,而是由元素添加到容器里的次序决定。

顺序容器包括:

vector(向量)、list(列表)、deque(队列)。

2、关联容器

关联式容器是非线性的树结构,更准确的说是二叉树结构。排序的容器底层是通过红黑树实现的,散列的是通过哈希表实现的。

关联容器可分为两类:

(1)有序的:map(集合)、set(映射)、multimap(多重集合)、multiset(多重映射)。
(2)无序的:unordered_mapunordered_setunordered_multimapunordered_multiset

3、容器适配器
C++提供了三种容器适配器(container adapter):stack,queue和priority_queue。stack和queue基于deque实现,priority_queue基于vector实现。

适配器包括:

stack(栈) 、queue(队列) 、priority_queue(优先级队列) 。

容器类自动申请和释放内存,因此无需new和delete操作。

2、顺序型容器

2.1 vector容器

1、简介

头文件 #include <vector>

vector是STL提供的动态数组,数组的大小可以动态的变化,类似与一个线性数组,索引效率高,插入,删除的效率很低,需要遍历数据列表。

2、优缺点:

优点:支持随机访问,即 [] 操作和 .at(),查询效率高。
缺点:当向头部或中部,插入或删除元素,插入效率低。

3、插入、删除的时间复杂度:
在这里插入图片描述
4、定义与初始化

	vector<int> vec1;    //默认初始化,vec1为空
	vector<int> vec2(vec1);  //使用vec1初始化vec2
	vector<int> vec3(vec1.begin(),vec1.end());//使用vec1初始化vec2
	vector<int> vec4(10);    //10个值为0的元素
	vector<int> vec5(10,4);  //10个值为4的元素
	vector<string> vec6(10,"null");    //10个值为null的元素
	vector<string> vec7(10,"hello");  //10个值为hello的元素

5、常用的操作方法

 	vec1.push_back(100);            //添加元素
    int size = vec1.size();         //元素个数
    bool isEmpty = vec1.empty();    //判断是否为空
    cout<<vec1[0]<<endl;        //取得第一个元素
    vec1.insert(vec1.end(),5,3);    //从vec1.back位置插入5个值为3的元素
    vec1.pop_back();              //删除末尾元素
    vec1.erase(vec1.begin(),vec1.end());//删除之间的元素,其他元素前移
    cout<<(vec1==vec2)?true:false;  //判断是否相等==、!=、>=、<=...
    vector<int>::iterator iter = vec1.begin();    //获取迭代器首地址
    vector<int>::const_iterator c_iter = vec1.begin();   //获取const类型迭代器
    vec1.clear();                 //清空元素

6、遍历方法

    //下标法(vector的特有访问方法,一般容器只能通过迭代器访问)
    int length = vec1.size();
    for(int i=0;i<length;i++) {
       cout<<vec1[i]<<endl;
    }
    //迭代器法
    vector<int>::const_iterator iterator = vec1.begin();
    for(;iterator != vec1.end();iterator++) {
       cout<<*iterator<<endl;
    }

2.2 list容器

1、简介

头文件 #include <list>

由 deque 实现而成,元素也存放在堆中。设计目的是令容器任何位置的添加和删除操作都很快速,作为代价不支持元素的随机访问——为了访问一个元素,只能遍历整个容器。

2、优缺点:

优点:内存不连续,动态操作,可在任意位置插入或删除且效率高。
缺点:不支持随机访问。

3、插入、删除的时间复杂度:
在这里插入图片描述
4、定义与初始化

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

5、常用的操作方法

 	lst1.assign(lst2.begin(),lst2.end());  //分配值
    lst1.push_back(10);                    //添加值
    lst1.pop_back();                   //删除末尾值
    lst1.begin();                      //返回首值的迭代器
    lst1.end();                            //返回尾值的迭代器
    lst1.clear();                      //清空值
    bool isEmpty1 = lst1.empty();          //判断为空
    lst1.erase(lst1.begin(),lst1.end());                        //删除元素
    lst1.front();                      //返回第一个元素的引用
    lst1.back();                       //返回最后一个元素的引用
    lst1.insert(lst1.begin(),3,2);         //从指定位置插入3个值为2的元素
    lst1.rbegin();                         //返回第一个元素的前向指针
    lst1.remove(2);                        //相同的元素全部删除
    lst1.reverse();                        //反转
    lst1.size();                       //含有元素个数
    lst1.sort();                       //排序
    lst1.unique();                         //删除相邻重复元素

6、遍历方法

//迭代器法
    for(list<int>::const_iterator iter = lst1.begin();iter != lst1.end();iter++) {
       cout<<*iter<<endl;
    }

2.3 deque容器

1、简介

头文件 #include <deque>

deque容器类与vector类似,支持随机访问和快速插入删除,它在容器中某一位置上的操作所花费的是线性时间。与vector不同的是,deque还支持从开始端插入数据:push_front()。其余类似vector操作方法的使用。

2、优缺点:

优点:支持随机访问,即 [] 操作和 .at(),查询效率高;当向两端,插入或删除元素,插入效率高。
缺点:当向中部,插入或删除元素,插入效率低。

3、插入、删除的时间复杂度:
在这里插入图片描述
4、定义与初始化

deque<int> c   ;  //产生一个空的deque,其中没有任何元素
deque<int> c1(c2); //产生另一个同型deque的副本(所有元素都被拷贝)
deque<int> c(n) ;  //产生一个大小为n的deque
deque<int> c(n , elem) ;  //产生一个大小为n的deque,每个元素值都是elem。
dequer<int> c(begin,end); //产生一个deque,以区间[begin ; end]做为元素初值

5、常用的操作方法

c.size();         //返回当前的元素数量
c.empty();       //判断大小是否为零。等同于c.size() == 0,但可能更快
c.max_size();    //可容纳元素的最大数量
c.at(idx) ;       //返回索引为idx所标示的元素。如果idx越界,抛出out_of_range
c[idx] ;         //返回索引idx所标示的元素。不进行范围检查
c.front() ;       //返回第一个元素,不检查元素是否存在
c.back();        //返回最后一个元素
c.begin();       //返回一个随机迭代器,指向第一个元素
c.end();         //返回一个随机迭代器,指向最后元素的下一位置
c1 = c2  ;        //将c2的所有元素赋值给c1;
c.assign(n , elem);    //将n个elem副本赋值给c
c.assing(beg , end);   //将区间[beg;end]中的元素赋值给c;
c.push_back(elem);   //在尾部添加元素elem
c.pop_back()    ;    //移除最后一个元素(但不回传)
c.push_front()   ;   //在头部添加元素elem
c.pop_front()    ;   //移除头部一个元素(但不回传)
c.erase(pos)    ;   //移除pos位置上的元素,返回一元素位置,如 c.erase( c.begin() + 5)移除第五个元素
c.insert(pos , elem); //在pos位置插入一个元素elem,并返回新元素的位置
c.insert(pos , n , elem); //在pos位置插入n个元素elem,无返回值
c.insert(pos , beg , end);
c.resize(num);       //将容器大小改为num。可更大或更小。
c.resize(num , elem);  //将容器大小改为num,新增元素都为 elem
c.clear();            //移除所有元素,将容器清空

3、有序关联容器

3.1 set(集合)和 multiset(多重集合)

1、简介

头文件 #include <set>

set(集合):由红黑树实现,其中每个元素只包含一个关键字并依据其值自动排序,支持高效的关键字查询操作,每个元素值只能出现一次,不允许重复。插入和删除效率比用其他序列容器高,因为对于关联容器来说,不需要做内存拷贝和内存移动。
multiset(多重集合):唯一的区别是插入的元素可以相同。

2、优缺点:

优点:关键字查询高效,且元素唯一,以及能自动排序。
缺点:每次插入值的时候,都需要调整红黑树,效率有一定影响。

3、插入、删除的时间复杂度:
在这里插入图片描述

4、定义与初始化

	set<int> iset(ivec.begin(), ivec.end());	// 根据迭代器范围内的元素初始化
	set<int> set1; 	// 创建一个空的set集合

5、常用的操作方法

	set1.insert("the"); //第一种方法:直接添加
	iset2.insert(ivec.begin(), ivec.end());//第二种方法:通过指针迭代器
    set1.size();    //元素个数
    set1.empty();   //判断空
    set1.find();	// 返回一个迭代器,此迭代器指向集合中其值与指定值相等的元素的位置。
    set1.begin();	// 返回一个迭代器,此迭代器指向集合中的第一个元素。
    set1.end();		// 返回超过末尾迭代器。
	set1.cbegin();	// 返回一个常量迭代器,此迭代器指向集合中的第一个元素。
	set1.cend();	// 返回一个超过末尾常量迭代器。

6、遍历方法

	//正向迭代器
    for(set<int>::iterator iter = set1.begin();iter!=set1.end();iter++) {
       cout << *iter << endl;
    }
    //反向迭代
	for(set<int>::iterator iter = set1.rbegin();iter!=set1.rend();iter++) {
       cout << *iter << endl;
    }

7、删除方法

	set1.erase(iterator it);	//删除迭代器指向的对象
	set1.erase(iterator first,iterator last);	//删除first到last迭代器范围中的内容
	set1.erase(value);	//通过值删除
	set1.clear();	// 清空所有元素,相对于set1.erase(set1.begin(),set1.end());

3.2 map(映射)和multimap(多重映射)

1、简介

头文件 #include <map>

map(映射):由红黑树实现,其中每个元素都是一些 键值对(key-value):关键字起索引作用,值表示与索引相关联的数据。每个元素有一个键,是排序准则的基础。每一个键只能出现一次,不允许重复。插入和删除效率比用其他序列容器高,因为对于关联容器来说,不需要做内存拷贝和内存移动。

multimap(多重映射):唯一的区别是插入的元素(值)可以相同,即同一个键可以对应多个值。
在这里插入图片描述

2、优缺点:

优点:关键字查询高效,且元素唯一,以及能自动排序。把一个值映射成另一个值,可以创建字典。
缺点:每次插入值的时候,都需要调整红黑树,效率有一定影响。

3、插入、删除的时间复杂度:
在这里插入图片描述

4、定义与初始化

	map<k, v>m 		// 创建一个名为m的空map对象,其键和值的类型分别为k和v
	map<k, v> m(m2) // 创建m2的副本m,m与m2必须有相同的键类型和值类型
	map<k, v> m(b, e) 	// 创建map类型的对象m,存储迭代器b和e标记的范围内所有元素的副本。元素的类型必须能转换为pair<const k, v>

5、常用的操作方法

	// 插入元素
	map1[3] = "Saniya";                    //添加一个键为 3,值为"Saniya"的键-值对
    map1.insert(map<int,string>::value_type(2,"Diyabi"));//插入元素
    map1.insert(pair<int,string>(1,"Siqinsini")); //插入一个pair类型的键-值对
    map1.insert(make_pair<int,string>(4,"V5")); //通过make_pair插入一个pair类型的键-值对
    map1.insert(iterator first,iterator last);	// 插入另一个map在迭代器范围内的数据
    //其他
	map<int,string>::iterator iter_map = map1.begin();//取得迭代器首地址
    int key = iter_map->first;             //取得key
    string value = iter_map->second;       //取得value
    map1.size();                       //元素个数
    map1.empty();                       //判断空
    map1.find();	// 返回一个迭代器,此迭代器指向映射中其键与指定键相等的元素的位置。
    map1.begin();	// 返回一个迭代器,此迭代器指向映射中的第一个元素。
    map1.end();		// 返回超过末尾迭代器。
	map1.cbegin();	// 返回一个常量迭代器,此迭代器指向映射中的第一个元素。
	map1.cend();	// 返回一个超过末尾常量迭代器。
	map1.count();	// 返回映射中其键与参数中指定的键匹配的元素数量。

6、遍历方法

	//正向迭代器
    for(map<int,string>::iterator iter = map1.begin();iter!=map1.end();iter++) {
       int keyk = iter->first;
       string valuev = iter->second;
    }
    //反向迭代
	for(map<int,string>::iterator iter = map1.rbegin();iter!=map1.rend();iter++) {
       int keyk = iter->first;
       string valuev = iter->second;
    }

7、删除方法

	map1.erase(iterator it);	//删除迭代器指向的对象
	map1.erase(iterator first,iterator last);	//删除first到last迭代器范围中的内容
	map1.erase(const Key&key);	//通过关键字删除
	map1.clear();	// 清空所有元素,相对于map1.erase(map1.begin(),map1.end());

4、无序关联容器

4.1 unordered_map/unordered_multimap

4.2 unordered_set/unordered_multiset

5、容器适配器

5.1 stack

1、简介

头文件 #include <stack>

C++ Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,——也就是说实现了一个先进后出(FILO)的数据结构。

2、插入、删除的时间复杂度:
在这里插入图片描述

3、常用的操作方法

	s1.empty() //堆栈为空则返回真
	s1.pop() //移除栈顶元素
	s1.push() //在栈顶增加元素
	s1.size() //返回栈中元素数目
	s1.top() //返回栈顶元素

5.2 queue

1、简介

头文件 #include <queue>

queue具有先进先出的数据结构。持新增元素、移除元素、从最底端加入元素、取最顶端元素。
在这里插入图片描述

2、插入、删除的时间复杂度:
在这里插入图片描述

3、常用的操作方法

	q.push(x); 	//入队,将x元素接到队列的末端;
	q.pop(); 	//出队,弹出队列的第一个元素,并不会返回元素的值;
	q.front();  //访问队首元素
	q.back(); 	//访问队尾元素
	q.size(); 	// 访问队中的元素个数
	q.empty(); 	//判断队列是否为空

5.3 priority_queue

1、简介

头文件 #include <queue>

priority_queue实现了优先队列这一ADT,也就是我们常说的堆。但要明晰的是,优先队列是一种ADT,而堆是它的一种具体实现。在默认状态下,priority_queue实现的是大根堆,但你可以通过模板特化从而实现小根堆。

定义:priority_queue<Type, Container, Functional>

Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式。

当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆,如下所示:

 //升序队列,小顶堆
 priority_queue <int,vector<int>,greater<int> > q;
 //降序队列,大顶堆
 priority_queue <int,vector<int>,less<int> >q;
 //greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。
 //其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)

2、插入、删除的时间复杂度:
在这里插入图片描述

3、常用的操作方法

	q.push(x); 	//入队,将x元素接到队列的末端,(并排序)
	q.pop(); 	//出队,弹出队列的第一个元素,并不会返回元素的值;
	q.front();  //访问队首元素
	q.back(); 	//访问队尾元素
	q.size(); 	// 访问队中的元素个数
	q.empty(); 	//判断队列是否为空

未完待续…

参考:https://blog.csdn.net/u014465639/article/details/70241850
https://blog.csdn.net/like_that/article/details/98446479
https://blog.csdn.net/weixin_43844677/article/details/104902417

原创文章 62 获赞 133 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43142797/article/details/105851147