STL入门学习与STL总结--更新中

从大一下学习C++,老师就说STL是C++精华,“C语言的指针,C++的STL”,结果一直都没什么时间专门去学STL,结果现在到了大三下为了保研夏令营,要开始学习STL咯;

目录

1、STL介绍

2、STL容器--vector

1、vector的定义:

2、vector访问

3、vector实例解析

4、vector的常见用途

2、STL容器 --set

1、set定义

2、set容器内元素访问

3、set常用函数实例解析

4、set的常见用途

3、STL容器--string

1、string的定义与访问

2、通过迭代器访问

3、常用函数解析

4、STL容器--map

1、map的定义

2、map元素访问

3、常用函数解析

4、常见用途

5、STL容器--queue(无迭代器)

1、定义

2、常用函数解析

3、常见用途

6、容器--Stack(无迭代器)

1、定义

2、常用函数解析

7、STL常用算法

1、max() min()

2、abs()

3、swap(x,y)

4、reverse(it,it2)

5、next_permutation(it1,it2)

6、sort()

7、max_element 、min_element

8、__gcd(x,y)

8、Pair容器

1、Pair容器的定义

2、Pair对象的操作

3、Pair类型作为哈希表的key

9、Priority_queue优先队列

1、常见方法

2、构造函数

3、元素是pair的priority_queue

4、自定义类型的优先队列

5、例子

10、list

1、构造函数

2、常见函数




1、STL介绍

STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间。

 STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但这种分离确实使得STL变得非常通用。例如,由于STL的sort()函数是完全通用的,你可以用它来操作几乎任何数据集合,包括链表,容器和数组;

   STL另一个重要特性是它不是面向对象的。为了具有足够通用性,STL主要依赖于模板而不是封装,继承和虚函数(多态性)——OOP的三个要素。你在STL中找不到任何明显的类继承关系。这好像是一种倒退,但这正好是使得STL的组件具有广泛通用性的底层特征。另外,由于STL是基于模板,内联函数的使用使得生成的代码短小高效;

STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类。

组成的库来说提供了更好的代码重用机会。在C++标准中,STL被组织为下面的13个头文件:<algorithm>、<deque>、<functional>、<iterator>、<vector>、<list>、<map>、<memory>、<numeric>、<queue>、<set>、<stack>和<utility>。

STL中六大组件:

   1)容器(Container),是一种数据结构,如list,vector,和deques ,以模板类的方法提供。为了访问容器中的数据,可以使用由容器类输出的迭代器;

   2)迭代器(Iterator),提供了访问容器中对象的方法。例如,可以使用一对迭代器指定list或vector中的一定范围的对象。迭代器就如同一个指针。事实上,C++的指针也是一种迭代器。但是,迭代器也可以是那些定义了operator*()以及其他类似于指针的操作符地方法的类对象;

   3)算法(Algorithm),是用来操作容器中的数据的模板函数。例如,STL用sort()来对一个vector中的数据进行排序,用find()来搜索一个list中的对象,函数本身与他们操作的数据的结构和类型无关,因此他们可以在从简单数组到高度复杂容器的任何数据结构上使用;

   4)仿函数(Function object)

   5)迭代适配器(Adaptor)

   6)空间配制器(allocator)

2、STL容器--vector

vector是一个比较常用的容器之一,翻译成向量,也可以叫做变长数组

使用前需要加入#include《vector》;以及using namespace std;

1、vector的定义:

vector <typename> name

typename可以是int,char,或者是STL容器,需要注意的是,假如typename也是STL容器的话,定义的时候记得在>>之间加空格

vector <int> age;
vector <vector <int> > age;  //类似于二维数组

// 二维数组还可以这么定义
vector <int> age[100];

//vector的构造函数
vector(size_type Count);	创建一个大小为Count的向量vect
vector(size_type Count,const Type& Val);	创建一个大小为Count的向量,该向量中所有的元素都初始化为Val

//二维数组,第一维数组的长度为vn,值是一个数组,而这个数组的初值为MAX_INT,即为二维数组
vector<vector<int> > Graph(vertex_num, vector<int>(vertex_num, MAX_INT));

第二种二维数组定义确定了一维的范围【0-99】,age[0]到age[99]都是一个vector<int>

2、vector访问

(1)普通下标:vi[1]

(2)迭代器访问:迭代器是指针哦!!

vector<int>::iterator it;
it=vi.begin();
it=vi.begin()+3;  //和 “&vi[3]” 一样

  vi[i]和*(vi.begin()+i)是一样的

既然提到了.begin(),还要提一下.end(),和.begin()首元素地址不一样,.end()是末尾元素地址的下一个地址。end()作为迭代器末尾的标志,不存储任何元素。即左闭右开;

只有vetcor和string的迭代器才允许加上整数这种写法    (vi.begin()+3);

3、vector实例解析

(1)push_back(x):向末尾添加一个元素x,时间复杂度为O(1)

(2)pop_back():末尾删除一个元素,时间复杂度为O(1)

(3)size():获得vector元素个数,时间复杂度为O(1)

(4)clear():清除所有元素,时间复杂度为O(N)

(5)insert(it,x):在迭代器it位置插入元素x,时间复杂度为O(N);原来的元素向后移

(6)erase(it):在迭代器it位置删除元素

(7)erase(first,last):在迭代器[ first,last )位置删除元素,不包括last

//删除vi[1],vi[2],vi[3]
vi.erase(vi.begin()+1,vi.begin()+4);

4、vector的常见用途

(1)存储数据

作为数组使用可以节省空间;

无需提前知道有多少个数据

(2)用邻接表存储图

2、STL容器 --set

set翻译成集合,是一个内部自动有序不重复的容器。

需要提前加入#include <set>

1、set定义

和vector一样

set<int> age;

2、set容器内元素访问

set的元素只能通过迭代器访问:

set<char>::iterator it;

只有vetcor和string的迭代器才允许加上整数这种写法    (vi.begin()+3);

因此在set中遍历元素只能自增:it++或者++it

对了,不支持it<st.end()这种写法,遍历只能it!=st.end()这样写

3、set常用函数实例解析

(1)insert(x),插入元素x在set中,自动去重排序,时间复杂度为O(logN)

(2)find(value),返回set中对应值为value的迭代器,时间复杂度为O(logN) //没找到就是set.end()

(3)erase(it),在迭代器it位置删除元素,时间复杂度为O(1)

(4)erase(value),在迭代器删除元素value,时间复杂度为O(logN)

(5)erase(first,last):在迭代器[ first,last )位置删除元素,不包括last,时间复杂度为O(lats-first)

(6)size():获得set元素个数,时间复杂度为O(1)

(7)clear():清除所有元素,时间复杂度为O(N)

4、set的常见用途

自动排序且按升序排序 

(1)multiset 不用处理唯一情况

(2)unordered_set 只去重不排序,速度比set快

3、STL容器--string

为了防止出现使用char[]而产生的错误,STL使用string来对字符串进行操作

同样,需要加入#include <string>

1、string的定义与访问

string str;

cin >> str;  //输入

printf("%c",str[1]);
cout << str;  //输出

输入输出string只能使用cin、cout,如果偏要使用printf(),那么c_str()将string转化为字符数组进行输出

printf("%s",str.c_str());

2、通过迭代器访问

和其他容器不一样,string的迭代器不需要参数

string::iterator it1;

通过迭代器可以访问string的每一位,且string迭代器和vector迭代器一样,可以直接加减数字

3、常用函数解析

(1)operator +=

(2)==   !=   >=  <=  比较方法是字典序

(3)length() size()

(4)insert(it,it2,it3)   被插入的位置是it,插入的字符串是 [ it2 , it3)

(5)erase(it) 删除单个字符

(6)erase(first,last):在迭代器[ first,last )位置删除元素,不包括last,时间复杂度为O(lats-first)

(7)erase( pos,length):pos为开始需要删除的位置,length为长度

(8)clear()  清空字符串,时间复杂度为O(1)

(9)substr(pos,len) 返回从位置从pos,长度为len的字符串子串

(10) find(str2) 返回str2出现的第一次次数,如果没有,返回string::npos 即-1,时间复杂度为O(m*n)

(11) find(str2,pos) 从Pos位置开始匹配,返回值与上面一样,时间复杂度为O(m*n) 

(12)replace(pos,len,str2) 从pos 开始,长度为n的字符串被取代为str2,两个字符长度不一定要相同

(13)replace(it1,it2,str2)  [it1,it2)的字符串被取代为str2,两个字符长度不一定要相同

4、STL容器--map

1、map的定义

键可以是字符串,可以是char,但是不能是char数组,map的键和值都可以是STL 容器

值得注意的是,Map需要两个tyoe,前者是键,后者是值

map<string,double> mp1;

map< set<int>,int >mp2;

2、map元素访问

1)通过下标

mp['c']=30  //定义且赋值
mp['c']=20  //更改值

2)通过迭代器访问

map<string, int>::iterator it1;

it1->first是键

it2->second是值

map的键也会从小到大排序,由于map内部是红黑树实现(set也是这样实现)

3、常用函数解析

(1)find(key) 返回键为key的迭代器,时间复杂度为O(logN)

(2)erase(it1) 删除单个元素,参数是迭代器

(3)erase(key) 删除单个元素,参数是键名

(4)erase(it1,it2) 删除区间内的元素,参数是迭代器

(5)size()  大小

(6)clear() 清空map中的元素

(7)lower_bound(key)  返回一个指向当前map容器中第一个大于或等于key键值对的双向迭代器

(8)upper_bound(key). 返回一个指向当前map容器中第一个小于或等于key键值对的双向迭代器


4、常见用途

  1. 需要判断大整数或者其他数据类型是否存在的问题,可以把map当作bool数组使用
  2. 字符串与字符串的映射需要用到需要建立字符(串)与整数之间映射关系

queue和stack千万注意:

1、for循环当中条件判断中有.size(),因为在pop\push之后会size会动态变化

最好是使用while(!stack1.empty())

2、push()和pop()没有返回元素

5、STL容器--queue(无迭代器)

queue是访问限制性函数,只允许先进先出每一次只允许使用front()访问队首元素,使用back()访问队尾元素

1、定义

#include <queue>
using namespace std;

queue<int> queue1;

2、常用函数解析

以下函数时间复杂度都为O(1)

  1. push(x),将x从队尾入列
  2. x=front( ) 队首元素
  3. x=back( ) 队尾元素
  4. pop() 队首元素出列
  5. empty()  判断是否为空
  6. size() 大小

3、常见用途

当需要 实现广度优先搜索时,可以直接使用queue

注意!:使用front()和back()前需要判断是否为空empty(),否则会出现错误

延伸:

  • deque()双端队列:首尾皆可以插入删除
  • priority_queue():使用堆实现的默认将当前队列最大的元素置于队首的容器

6、容器--Stack(无迭代器)

使用#include<stack>

只有栈顶元素可以被外界使用,也就是说 stack 不具有遍历行为,没有迭代器

1、定义

#include<stack>
using namespace std;

stack<int> s1;
stack<int> s2(s1);

2、常用函数解析

push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素

empty();//判断堆栈是否为空
size();//返回堆栈的大小

7、STL常用算法

使用#include <algorithm> 

1、max() min()

这两个函数的参数只能是两个

2、abs()

返回绝对值,参数必须是整数,如果是浮点数,那么必须用math的fabs

3、swap(x,y)

交换x,y的值

4、reverse(it,it2)

将数组指针或者容器迭代器在[it,it2)范围内的元素进行反转

5、next_permutation(it1,it2)

给出一个序列的下一个全排列序列

利用next_permutation的返回值,判断是否全排列结束(否则将死循环)

注意!!!

一开始是从当前序列“1,2,5,4,3”开始,而不是自动排好序开始

知道输出完最大全排序“5,4,3,2,1”之后,当前全排列变成最小的全排序序列“1,2,3,4,5”

6、sort()

需要头文件<algorithm>

语法描述:sort(begin,end,cmp),cmp参数可以没有,如果没有默认非降序排序。

对数组升序:sort(a,a+5);

若设计为非升序排序,则cmp函数的编写:

bool cmp(int a,int b){

  return a>b;

}

7、max_element 、min_element

从一个范围中获取最大/最小的元素的地址,记住是地址

8、__gcd(x,y)

__gcd(x,y)是algorithm库中的函数,主要是用于求两个数的最大公约数

8、Pair容器

pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同

1、Pair容器的定义

基本的定义如下:

pair<int, string> a;

pair<string, string> a("James", "Joy");

2、Pair对象的操作

1、对于pair类,由于它只有两个元素,分别名为first和second,因此直接使用普通的点操作符即可访问其成员

pair<string, string> a("Lily", "Poly"); 
string name;
name = pair.second;

2、生成新的pair对象

可以使用make_pair对已存在的两个数据构造一个新的pair类型:

int a = 8;
string m = "James";
pair<int, string> newone;
newone = make_pair(a, m);

3、Pair类型作为哈希表的key

// 1、首先实现hash function
struct hash_pair { 
    template <class T1, class T2> 
    size_t operator()(const pair<T1, T2>& p) const
    { 
        auto hash1 = hash<T1>{}(p.first); 
        auto hash2 = hash<T2>{}(p.second); 
        return hash1 ^ hash2; 
    } 
}; 

// 2、接下来把这个hash函数传给unordered_map就OK了!
unordered_map<pair<int,int>, int, hash_pair> um;

// 因为map容器并不需要hash函数,所以将key设置为pair是不会报错的。在数据量不大的情况下,也可以考虑使用map替代unordered_map,性能并不会有太大差异。

9、Priority_queue优先队列

首先要包含头文件#include<queue>, 他和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队。

1、常见方法

  • top 访问队头元素
  • empty 队列是否为空
  • size 返回队列内元素个数
  • push 插入元素到队尾 (并排序)
  • emplace 原地构造一个元素并插入队列
  • pop 弹出队头元素
  • swap 交换内容

2、构造函数

//升序队列,小顶堆
priority_queue <int,vector<int>,greater<int> > q;
//降序队列,大顶堆
priority_queue <int,vector<int>,less<int> >q;

//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数)

3、元素是pair的priority_queue

priority_queue<pair<int, int> > a;

默认只按照第一个成员,即first来排序,如果相等按照第二个元素

4、自定义类型的优先队列

#include <iostream>
#include <queue>
using namespace std;

//方法1
struct tmp1 //运算符重载<
{
    int x;
    tmp1(int a) {x = a;}
    bool operator<(const tmp1& a) const
    {
        return x < a.x; //大顶堆
    }
};

//方法2
struct tmp2 //重写仿函数
{
    bool operator() (tmp1 a, tmp1 b) 
    {
        return a.x < b.x; //大顶堆
    }
};

5、例子

一个可以使用优先队列求解的问题:使用的是pair优先队列,https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/https://leetcode-cn.com/problems/hua-dong-chuang-kou-de-zui-da-zhi-lcof/

10、list

list:list就是数据结构中的双向链表(根据sgi stl源代码),内存空间是不连续的,没有提供[]操作符的重载。可以很好的效率支持任意地方的删除和插入。

1、构造函数

list() 声明一个空列表;

list(n) 声明一个有n个元素的列表,每个元素都是由其默认构造函数T()构造出来的

list(n,val) 声明一个由n个元素的列表,每个元素都是由其复制构造函数T(val)得来的

list(n,val) 声明一个和上面一样的列表

list(first,last) 声明一个列表,其元素的初始值来源于由区间所指定的序列中的元素

2、常见函数

begin和end获取的是迭代器,front和back是元素

begin()和end():通过调用list容器的成员函数begin()得到一个指向容器起始位置的iterator,可以调用list容器的 end() 函数来得到list末端下一位置

push_back() 和push_front()

pop_back和pop_front():通过删除最后一个元素,通过pop_front()删除第一个元素;序列必须不为空,如果当list为空的时候调用pop_back()和pop_front()会使程序崩掉。

front()和back(): 通过front()可以获得list容器中的头部元素,通过back()可以获得list容器的最后一个元素

insert():在指定位置插入一个或多个元素(三个重载):

l1.insert(l1.begin(),100); 在l1的开始位置插入100。

l1.insert(l1.begin(),2,200); 在l1的开始位置插入2个100。

l1.insert(l1.begin(),l2.begin(),l2.end());在l1的开始位置插入l2的从开始到结束的所有位置的元素。

erase():删除一个元素或一个区域的元素(两个重载)

l1.erase(l1.begin()); 将l1的第一个元素删除。

l1.erase(l1.begin(),l1.end()); 将l1的从begin()到end()之间的元素删除。

参考资料:

【1】《算法笔记》--胡凡

【2】《C++标准模板库(STL)—简介》--https://blog.csdn.net/qing101hua/article/details/70313550 

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STL是指标准模板库(Standard Template Library),它是C++语言的一部分,提供了一系列的模板类和函数,用于支持通用的数据结构和算法。STL的目标是提供高效、可重用和可扩展的组件,以便开发人员能够更轻松地编写高质量的代码。STL包含了许多常见的数据结构,如vector、list、set、map等,以及各种算法,比如排序、查找、遍历等。通过使用STL,开发人员可以更加高效地处理各种数据结构和算法的问题,提高代码的开发效率和质量。 在STL,我们可以使用各种容器来存储和管理数据。例如,我们可以使用std::map来创建一个键值对的映射,其每个键都有一个与之相关联的值。下面是一个示例代码,展示了如何创建和使用一个std::map对象: std::map<std::string, int> disMap() { std::map<std::string, int> tempMap{ {"C语言教程",10},{"STL教程",20} }; return tempMap; } std::map<std::string, int> newMap(disMap()); 在这个示例,disMap()函数创建了一个临时的std::map对象,并初始化了其的一些键值对。然后,使用移动构造函数将这个临时对象移动到了一个新的std::map对象newMap。最终,我们可以通过newMap对象来访问和操作这些键值对。 综上所述,STLC++的标准模板库,提供了一系列的模板类和函数,用于支持通用的数据结构和算法。STL的使用可以提高代码的开发效率和质量,并且通过各种容器和算法,可以方便地处理各种数据结构和算法的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++ STL详解超全总结(快速入门STL)](https://blog.csdn.net/qq_50285142/article/details/114026148)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【C++实验】阅读STL源码并分析](https://blog.csdn.net/qq_35760825/article/details/125311509)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值