STL简单应用学习总结笔记(一)(21.3.13)

本周主要学习了字符串(string)、栈(Stack)、队列(queue)、动态数组(vector)、优先队列(priority_queue)、set和multiset、map和multimap以及sort函数、去重(unique)、生成排列、upper_bound 和 lower_bound。学的比较多,主要是了解相关简单用法,熟悉基本操作,并学会在解题中用STL知识优化解题步骤。刚开始接触STL,发现许多容器的用法有一定的相似之处,之前做了一些题,也不太能分清楚STL里各种容器等的用途及用法,现将它们放在一起做一些简单汇总,以下为知识点的简单整理回顾。(心得体会在最后)

字符串string类
1.头文件#include<string>

常用操作 说明
os<<s 将s写到输出流os中,返回os
is>>s 从输入流is读取字符串赋给s,字符串以空白分隔,返回is
getline(is,s) 从输入流is中读取一行赋给s,返回is
s.empty() s为空返回true,否则返回false
s.size() 返回s中字符的个数
s[n] 返回s中第n个字符的引用,位置n从0开始计
s.c_str() 转换,返回s中内容对应的c风格字符串首地址
s1=s2 赋值,用s2的副本替换s1原来的内容
s1+s2 连接,返回s1和s2连接后的结果
s1+=s2 追加,把s2的内容追加到s1后面
s1==s2 如果s1和s2长度相同且字符完全一样,则相等;
s1!=s2 string对象的比较对字母区分大小写
<,<=,>,>= 利用字符在字典中的顺序进行比较,宇母区分大小写

2.string的创建

 string s1,s2;  //创建两个空字符串对象
 string s3="Hello,Word!";  //创建s3,并初始化
 string s4("I am");  //创建s4,并初始化
 s2="Today"; //对对象赋值  

3.读写string对象

  • 使用标准库中iostream可以读写string对象
  • 可用循环读取未知数量的string对象
  • getline()函数
    两个参数:输入流对象和string对象
    遇到换行符为止,空格可被读入。
    返回参数输入流对象
    string line; while(getline(cin, line)) cout << line << endl;

栈(Stack)
在这里插入图片描述
1.说明:栈是一种后进先出的数据结构,在STL的stack中只能通过top()来访问栈顶元素。栈只能在某一端插入和删除数据,先进的数据被压入栈底,最后进入的数据在栈顶(即允许进行插入删除操作的一端称为栈顶,另一端称为栈底)
2.定义:头文件#include <stack>
stack<data_type> stack_name;
如:stack <int> s;
3.操作:

empty() -- 返回bool型,表示栈内是否为空 (s.empty() )
size() -- 返回栈内元素个数 (s.size() )
top() -- 返回栈顶元素值 (s.top() )
pop() -- 移除栈顶元素(s.pop(); )
push(data_type a) -- 向栈压入一个元素a   (s.push(a); )

4.常见用途
用栈来模拟实现一些递归,防止程序对栈内存的限制而导致程序运行出的错。一般来说, 程序的栈内存空间很小,对有些题目来说,如果用普通的函数来进行递归,一旦递归层数过深(则会导致程序运行崩溃。如果用栈来模拟递归算法的实现,则可以避免这一方面的问题。

队列(queue)
在这里插入图片描述
1.说明:队列是一种先进先出的数据结构,在STL中只能通过front()访问队首元素,通过back()访问队尾元素,从底端加入元素,从顶端取出元素。
2.定义:头文件#include <queue>
queue <data_type> queue_name
如:queue <int> q
3.操作:

empty() -- 返回bool型,表示queue是否为空 (q.empty() )
size() -- 返回queue内元素个数 (q.size() )
front() -- 返回queue内的下一个元素 (q.front() )
back() -- 返回queue内的最后一个元素(q.back() )
pop() -- 移除queue中的一个元素(q.pop(); )
push(data_type a) -- 将一个元素a置入queue中(q.push(a); )

4.常见用途
当需要实现广度优先搜索时,可以不用自己手动实现一个队列,而是用队列作为代替,以提高程序的准确性。
注意:使用front()和pop()函数前,必须用empty()判断队列是否为空,否则可能因为队空而出现错误。
延伸:STL的容器中还有两种容器跟队列有关,分别是双端队列(deque)和优先队列(priority_queue),前者是首尾皆可插入和删除的队列,后者是使用堆实现的默认将当前队列最大元素置于队首的容器。

优先队列(priority_queue)
在这里插入图片描述
1.说明:优先队列底层是用堆来进行实现的。在优先队列中,队首元素一定是当前队列中优先级最高的那一个。
可以在任何时候往优先队列里面加入(push)元素,而优先队列底层的数据结构堆(heap)会随时调整结构,使得每次的队首元素都是优先级最大的。
2.定义:头文件: #include <queue>
priority_queue <data_type> priority_queue_name;
如:priority_queue <int> q;//默认是大顶堆
3.操作:

q.push(elem) 将元素elem置入优先队列
q.top() 获得队首元素
q.pop() 移除队首元素
q.size() 返回队列中元素的个数
q.empty() 返回优先队列是否为空

4.注意:和队列不一样的是,优先队列没有front()函数与back()函数,而只能通过top()函数来访问队首元素,也就是优先级最高的元素。
5.priority_queue<int, vector<int>, less<int>> q;
这种定义多了两个参数:一个是vector,另一个是less。其中vector(也就是第二个参数)填写的是来承载底层数据结构堆(heap)的容器,第三个参数less则是对第一个参数的比较类,less表示数字大的优先级越大,而greater表示数字小的优先级越大。
如果想让优先队列总是把最小的元素放在队首,只需进行如下定义:
priority_queue<int, vector<int >, greater<int>>q;

# include < stdio.h>
 #include <queue> 
 using namespace std;
int main () 
{
    
        priority_queue<int, vector<int>, greater<int>> q;
    q.push (3);
    q.push (4);
    q.push (1);
    printf ("d\n", q.top ())}

输出结果为1
6.常见用途
优先队列可以解决一些贪心问题,注意,使用top()函数前,必须用empty()判断优先队列是否为空,否则可能因为队空而出现错误。

Vector-动态数组
1.说明:变长数组,长度根据需要而自动改变的数组。
2.定义:头文件#include<vector>
vector <data_type> vector_name
如:vector <int> v
数组定义:vector<typename> Arrayname[arraysize]
如:vector<int> vi[100]
3.操作:

empty() -- 返回bool型,表示vector是否为空 (v.empty() )
size() -- 返回vector内元素个数 (v.size() ),返回unsigned类型
push_back(data_type a) --将元素a插入最尾端(v.push_back())
pop_back()-- 将最尾端元素删除(v.pop_back())
v[i]-- 类似数组取第i个位置的元素(v[0] )
clear()--清空vector中所有元素(v.clear())
insert()--insert(it,x)向vector的任意迭代器it处插入元素x   (如:v.insert(v.begin() + 2 , -1 );-1插入v[2]的位置)
erase()--两种用法:删除单个元素erase(it)、删除一个区间内的所有元素erase(first, last)即删[first, last)
v.erase(v.begin() ,  v.end())

通过迭代器访问:
1)定义:vector<typename>::iterator it
如:vector<int>::iterator it
可用* it来访问vector里的元素
2)v[i]等价于*(v.begin() + i)

vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++)
cout<<*it<<endl;

set 和 multiset
1.说明:set为集合,是一个内部自动有序且不含重复元素的容器。multiset内部自动有序可以允许元素重复。
2.头文件: #include <set>
定义:set <data_type> set_name
如:set <int> s;//默认由小到大排序
数组定义:set<typename> Arrayname[arraysize]
如:set<int> a[100]
如果想按照自己的方式排序,可以重载小于号。
关于运算符重载https://blog.csdn.net/weixin_34023863/article/details/85886339?utm_source=app&app_version=4.5.3

struct new_type
{
    
    
		int x, y;
		bool operator < (const new_type &a)const
		{
    
    
			if(x != a.x) return x < a.x;
			return y < a.y;
		}
}set <new_type> s;

3.操作:

s.insert(elem) -- 安插一个elem副本,返回新元素位置。
s.erase(elem) -- 移除与elem元素相等的所有元素,返回被移除	的元素个数。
s.erase(pos) -- 移除迭代器pos所指位置上的元素,无返回值。
s.find(value)--返回set中对应值为value的迭代器
s.clear() -- 移除全部元素,将整个容器清空。
s.size() -- 返回容器大小。
s.empty() -- 返回容器是否为空。
s.count(elem) -- 返回元素值为elem的元素的个数。
s.lower_bound(elem) -- 返回元素值>= elem的第一个元素位置。
s.upper_bound(elem) -- 返回元素值 > elem的第一个元素的位置。
以上位置均为一个迭代器。
s.begin() -- 返回一个双向迭代器,指向第一个元素。
s.end() -- 返回一个双向迭代器,指向最后一个元素的下一	个位置

4.实例用法

#include<iostream>
#include<set>
using namespace std;
int main()
{
    
    
    ios::sync_with_stdio(false);
    set<string>sl;
    set<string>::iterator iterl;//迭代器
    sl.insert("abc");
    sl.insert("abc");
    sl.insert("abc");
    sl.insert("bca");
    sl.insert("aa");
    cout<<"ITERATE:"<<endl;
    for(iterl=sl.begin(); iterl!=sl.end(); iterl++)
        cout << (*iterl) <<endl;
    cout<<"FIND:"<<endl;
    iterl=sl.find("abc");//查找
    if(iterl!=sl.end())
    {
    
       cout<<*iterl<<endl;
    }
    else
    {
    
       cout<<"NOT FOUND"<<endl;//查找到第一个无效位
    }
    return 0;
}
ITERATE:
aa
abc
bca
FIND:
abc

5.注意:

  • set只能通过迭代器(iterator)访问
  • 除vector和string外STL不支持*(it+i)的访问方式,只能枚举。
    set元素自动递增。

6.set常见用法
最主要的作用是自动去重并按升序排序,因此碰到需要去重但是却不方便直接开数组的情况,可以尝试用set解决

map和multimap
1.说明:map是映射,可以将基本类型映射到任何基本类型,如:字典,字符串->页码类似于映射。所有元素都会根据元素的键值从小到大自动排序,map的所有元素都是pair,pair的第一个元素被视为键值,第二个元素为实值。map不允许两个元素有相同的键值,但multimap可以。
2.头文件:#include <map>
定义:map <data_type1, data_type2> map_name
如:map <string, int> m//默认按string由小到大排序
3.操作:

m.size() 返回容器大小
m.empty() 返回容器是否为空
m.count(key) 返回键值等于key的元素的个数
m.lower_bound(key) 返回键值等于key的元素的第一个可安插	的位置
m.upper_bound(key) 返回键值等于key的元素的最后一个可安插的位置
m.begin() 返回一个双向迭代器,指向第一个元素。
m.end() 返回一个双向迭代器,指向最后一个元素的下一个位置。
m.clear() 讲整个容器清空。
m.erase(elem) 移除键值为elem的所有元素返回个数,对于map来说非01。
m.erase(pos) 移除迭代器pos所指位置上的元素。
m.insert(elem) 插入一个元素elem
	a)运用value_type插入
		map<string, float> m;
		m.insert(map<string, float>:: value_type ("Robin", 22.3));
	b) 运用pair<>
		m.insert(pair<string, float>("Robin", 22.3));
	c) 运用make_pair()
		m.insert(make_pair("Robin", 22.3));

直接元素存取:
m[key] = value;
查找的时候如果没有键值为key的元素,则安插一个键值为key的新元素,实值为默认(一般0)。
4.map元素的访问
1)下标访问,类似数组
2)迭代器访问map<typename1,typename2>::iterator it;
用it->first访问键,用it->second访问值
5.map用途

  • 建立字符(或字符串)与整数之间映射的题目,使用map可以减少代码量。
  • 判断大整数或者其他类型数据是否存在的题目,可以把map当bool数组用。
  • 字符串和字符串的映射也有可能会遇到。

去重函数(unique)
去除容器或者数组中相邻元素的重复出现的元素

  • 去除并非真正意义的erase,而是将重复的元素放到容器的末尾,返回值是去重之后的尾地址。
  • unique针对的是相邻元素,需要先进行排序,sort().
iterator unique(iterator begin,iterator);//对区间[it_1,it_2)内进行去重
iterator unique(iterator begin,iterator end,bool MyFunc);//最后一个参数是元素是否相等的判定函数。返回值是指向最后一个元素的下一个元素的迭代器

生成排列
头文件: #include <algorithm>

bool next_permutation(begin, end);
改变区间内元素的顺序,产生下一个排列。
bool prev_permutation(begin, end);
产生前一个排列。
end为最后一个元素的下一个位置。

upper_bound 和 lower_bound

upper_bound(begin, end, value); 
返回>value的元素的第一个位置。
lower_bound(begin, end, value);
返回>=value的元素的第一个位置。

另外
学习宏定义

#define pow2(a) ((a)*(a))
#define dist2(x, y) (pow2(x) + pow2(y))
  #define rep(i,a,n) for (int i=a;i<=n;i++)//i为循环变量,a为初始值,n为界限值,递增
  #define per(i,a,n) for (int i=a;i>=n;i--)//i为循环变量, a为初始值,n为界限值,递减。
  #define pb push_back
  #define IOS ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
  #define fi first
  #define se second
  #define mp make_pair

心得体会:
本周学习了STL的一些简单用法,结合假期里自学的一点相关知识,对STL有了更多了解,在目前阶段的学习中,STL是一种比较简便的工具可以帮助我们快速解决一些问题,之前在做一些问题的时候用普通的方式解决问题又复杂又难构思,不如借助STL工具更加方便快捷,比如用两个对应数组解决不如用map方便,其他一些题就不列举了。STL里的容器的使用方式有一定的相似之处,可以对比着去记忆,目前我用STL工具还不够熟练,还需要在做题中反复尝试使用。

猜你喜欢

转载自blog.csdn.net/weixin_51443397/article/details/114726947