C++ STL总结 - 基于算法竞赛

写在前面

由于本人实力尚浅,接触算法没多久,写这篇blog仅仅是想要提升自己对算法的理解,如果各位读者发现什么错误,恳请指正,希望和大家一起进步。(●’◡’●)

1.vector

vector

声明

using namespace std;
#include<vector>		//引入头文件
vector<int> a;			//相当于长度动态变化的int数组
vector<int> b[88];		//相当于第一维长88,第二维长度动态变化的int数组(类似于b[88][])
struct rec {};
vector<rec> c;			//自定义的结构体;类型也可以保存在vector中

方法函数

代码含义时间复杂度
c.front()返回第一个数据O(1)
c.pop_back()删除最后一个元素O(1)
c.push_back()在尾部加一个元素O(1)
c.back()返回数组中的最后一个元素O(1)
c.size()返回实际长度O(1)
c.empty()返回一个bool类型,表面vector是否为空O(1)
c.clear()vector清空O(N)
c.begin()返回首元素的迭代器(通常来说是地址)O(1)
c.end()返回最后一个元素后一个位置迭代器(地址)O(1)

说明

  • begin()函数返回指向vector中第一个元素的迭代器。*c.begin()c[0]作用相同。
  • 所有容器都可以视作一个“前开后闭”的结构,返回最后一个元素后一个位置迭代器(地址),即第n个元素再往后的“边界”。c.end()c[n]都是越界访问,使用时要注意。
  • 遍历vector
	for (int i = 0; i < a.size(); i++)		//利用下标遍历		
		cout << a[i] << endl;

	for (vector<int>::iterator p = a.begin(); p != a.end(); p++)		//利用指针遍历
		cout << *p << endl;

2.queue

一种先进先出(FIFO)的数据结构。

声明

using namespace std;
#include<queue>
queue<int> q;
struct rec {}; queue<rec> q;

方法函数

方法含义时间复杂度
push在尾部压入一个元素O(1)
pop删除队头元素(即出队)O(1)
front取出队头元素O(1)
back取出队尾元素O(1)

说明

  • 没什么要说明的,这个数据结构很简单😂
  • 遍历queue
	while (!q.empty())
	{
		cout << q.front() << endl;
		q.pop();
	}

3.priority_queue

就是在正常队列的基础上加了优先级,保证每次的队首元素都是优先级最大的。
它的底层是通过堆来实现的,可以理解为一个大根二叉堆。

声明

#include<queue>
priority_queue<int> q;

方法函数

方法含义时间复杂度
push把元素插入堆 O ( l o g n ) O(log_n) O(logn)
pop删除堆顶元素 O ( l o g n ) O(log_n) O(logn)
top取到堆顶元素O(1)

说明

  • 注意queuepriority_queue取到队头(堆顶)元素的方法不一样。
  • priority_queue也有sizeempty(),只不过在前面的方法里我懒得写

设置优先级

基础数据类型的优先级
priority_queue<int, vector<int>, greater<int>> heap;		//小根堆,每次取出都是队列中最小的元素

参加解释:

  • 第一个参数:就是优先队列中存储的数据类型
  • 第二个参数:vector<int> 是用来承载底层数据结构堆的容器,若优先队列中存放的是double型数据,就要填vector< double >
    总之存的是什么类型的数据,就相应的填写对应类型。同时也要改动第三个参数里面的对应类型。
    至于承载底层数据结构堆的堆,我也没搞明白原理。 大家也没必要去搞明白,会用就可以了。
  • 第三个参数:greater<int>表示数字小的优先级大,堆顶为最小的数字。less<int>则与之相反。
    int代表的是数据类型,也要填优先队列中存储的数据类型
    大家平时使用上面这种写法就可以了,下面的自定义的排序并不推荐
struct cmp1 {
    bool operator()(int x, int y) {
        return x > y;
    }
};
struct cmp2 {
    bool operator()(const int x, const int y) {
        return x < y;
    }
};
priority_queue<int, vector<int>, cmp1> q1; // 小根堆
priority_queue<int, vector<int>, cmp2> q2; // 大根堆

关于设置优先级我在这里就不在赘述了,因为打算法比赛的话基本上掌握最基础的就完全够用了
想要了解更多的—>click here
priority_	queue

4.deque

双端队列是一个支持在两端高效插入或者删除元素的连续线性存储空间。
它就像是vectorqueue的结合。

声明

#include<deque>
deque<int> dq;

方法函数

方法含义时间复杂度
begin()/end()deque 的头/尾迭代器(地址)O(1)
front()/back()队头/队尾元素O(1)
push_back()/push_front()将元素插入队尾/队头O(1)
pop_back()/pop_front()删除队尾/队头元素O(1)
[]随机访问O(1)

5.set

set容器里的元素不会重复(multiset可以包含若干个相同的元素),当插入集合中已有的元素时,并不会插入进去,而且set容器里的元素自动从小到大排序。内部实现是一颗红黑树(平衡树的一种)
总的来说set里面的元素不重复 且有序

声明

#include<set>
set<int> s;
struct rec {}; set<rec> s;

方法函数

方法含义时间复杂度
size()/empty()/clear()分别为元素个数,是否为空,清空O(1)
find()查找某一元素,有则返回该元素对应的迭代器,无则返回结束迭代器
count()查找set中某一元素出现的次数,由于set元素唯一,相当于查询元素是否出现
begin()/end()和前面的容器的一样O(1)

由于set在算法比赛中使用的频次非常低(仅仅是根据我的个人理解,不对勿喷),所以这里我就只是简单介绍一下set,不做赘述。

6.map

map容器是一个键值对key-value的映射(映射类似于函数的对应关系,每一个x对应一个y),map中每个键对应一个值,和python中的字典非常相似。

声明

//头文件
#include<map>
//初始化定义
map<string, string> mp;
map<string, int> mp;
map<int, node> mp;//node是结构体类型

方法函数

方法含义
size()/empty)/begin()/end()和前面的容器一样
insert()插入元素,要以键值对形式插入
[][]里面是key,返回的是value
find()返回键为key的映射的二元组的迭代器 O ( l o g N ) O(log_N) O(logN)注意:用find函数来定位数据出现位置,它返回一个迭代器。当数据存在时,返回数据所在位置的迭代器,数据不存在时,返回mp.end()

说明

  • 使用mp.find(),mp.count(),mp[]key]均可以查找元素是否存在。
  • []操作符是map中最吸引人的地方,我们可以通过mp[key]来得到key对应的value,还可以对mp[key]进行赋值操作,改变对应key对应的value
  • 但是,若查找的key不存在时,mp会自动创建一个二元组(key,zero),返回zero的引用。这里的zero表示一个广义的“零值”,如整数0,空字符串等。如果查找之后不对其赋值,长时间下来就产生许多无用的零值二元组,白白占用空间降低程序运行效率,建议使用[]前先用find查询一下。
  • map特性:map会按照键的顺序从小到大自动排序,键的类型必须可以比较大小
  • 还有unordered_map,内部用哈希表实现,内部元素杂乱无章,但其实我觉得二者没什么大的区别,算法比赛中都可以使用。

7.stack

一种先进后出(FILO)的数据结构

声明

//头文件需要添加
#include<stack>

//声明
stack<int> s;
stack<string> s;
stack<node> s;//node是结构体类型

方法函数

方法含义时间复杂度
empty()/size()和前面的容器一样O(1)
top()取得栈顶元素(但是不删除)O(1)
push()将元素入栈O(1)
pop()移除栈顶元素O(1)

说明

  • 一般来说可以用一个数组来进行模拟,一个存放下标的变量top模拟指向栈顶的指针。
  • 还有单调栈的写法可以使用额外变量tthh来模拟,具体等我再写一篇关于单调栈的blog

8.pair

pair只含有两个元素,可以看作是只有两个元素的结构体。

pair<int, int> a;
pair<int, string> b;

应用

  • 代替二元结构体
  • 作为map的键值对进行插入

访问

p.first访问第一个元素,p.second访问第二个元素

//定义结构体数组
pair<int,int> p[20];
for(int i = 0; i < 20; i++) {
    //和结构体类似,first代表第一个元素,second代表第二个元素
    cout << p[i].first << " " << p[i].second;
}

string

string是一个字符串类,和char型字符串类似。和char[N]非常相似

声明

//头文件
#include<string>

//1.
string str1; //生成空字符串

//2.
string str2("123456789"); //生成"1234456789"的复制品 

//3.
string str3("12345", 0, 3);//结果为"123" ,从0位置开始,长度为3

//4.
string str4("123456", 5); //结果为"12345" ,长度为5

//5.
string str5(5, '2'); //结果为"22222" ,构造5个字符'2'连接而成的字符串

//6.
string str6(str2, 2); //结果为"3456789",截取第三个元素(2对应第三位)到最后

读入详解

  • 读入字符串,遇到空格,回车结束
string s;
cin >> s;
  • 读入一行字符串(包括空格),遇到回车结束
string s;
getline(cin, s);

注意:getline(cin,s)会获取前一个输入的换行符,需要在前面添加读取换行符的语句,如getchar(),下面是示例

int n;
string s;
cin >> n;
getchar(); //cin.get()
getline(cin, s);//可正确读入下一行的输入
  • cin和cout解锁
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);

为什么要进行cincout解锁
在一些题目中,读入的数据量很大,往往超过了1e5(105)的数据量,而cincout的读入输出的速度很慢(是因为cincout为了兼容C语言的读入输出在性能上做了妥协),远不如scanfprintf的速度,具体原因可以搜索相关的博客进行了解。
所以对cincout进行解锁使cincout的速度几乎接近scanfprintf,避免输入输出超时。
注意:cin cout解锁使用时,不能与 scanf,getchar, printf,cin.getline()混用,一定要注意,会出错。

感谢各位童鞋看到这里,这篇blog我还没有写完,几天后还会更新STL函数赶紧关注一波后面我会持续更新数据结构与算法,也希望大家点点赞,我们一起进步(❁´◡`❁)

  • 48
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C++ STL(Standard Template Library)是C++标准库中的一部分,它提供了一系列的模板类和函数,用于实现常见的数据结构和算法。数据结构和算法是计算机科学中的基础概念,用于解决各种问题。 区别在于: 1. 覆盖范围:C++ STL是一个广泛的库,提供了许多常用的数据结构和算法,如向量、链表、堆、哈希表、排序算法等等。而数据结构和算法是计算机科学的核心概念,涵盖了更广泛的范围,包括了更多的数据结构和算法的设计与实现。 2. 实现方式:C++ STL提供了模板类和函数的封装,可以直接使用这些类和函数来实现数据结构和算法。而数据结构和算法需要在具体的编程语言中进行实现,可以使用C++或其他编程语言来实现。 3. 使用方式:C++ STL提供了一种方便、高效的方式来使用常见的数据结构和算法,可以大大简化程序的开发和维护。而数据结构和算法需要开发者自己设计和实现,需要一定的算法知识和编程能力。 4. 扩展性:C++ STL是一个标准库,提供了一些常用的数据结构和算法,但不一定满足所有的需求。而数据结构和算法的实现可以根据具体的需求进行扩展和优化。 总的来说,C++ STL是一个方便、高效的工具,可以快速实现常见的数据结构和算法。而数据结构和算法是一门学科,需要深入理解和掌握,能够根据具体的问题进行设计和实现。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值