2022/03/13 C++标准模板库STL学习

1.vector

向量,又叫变长数组,当遇见只用普通数组会超内存的情况,使用vector会更便捷。
vector数组:可理解为两个维都可以变长的二维数组

#include<vector>;
using namespace std;

1.1定义

单独定义一个vector
vector<typename> name; //typename可以是任何基本类型(int、double、char、结构体)  
vector<vector<int> > name;/*如果是STL容器,定义时候 要在>>之间加空格,
                            避免误认为移位操作 */    
定义vector数组
vector<typename> Arrayname[arraysize];
比如 
vector<int> vi[100];/*vi[0]~vi[99]中每一个都是一个vector容器,与上面不同,这里的一维长度
                               已经固定*/

1.2 访问

1.2.1 下标访问

vector<typename> vi;
直接访问方式:vi[0] vi[1]     //访问范围为0到vi.size()-1

1.2.2 迭代器访问

vector<typename>::iterator it;/*iterator可以理解为类似指针,
                            定义了迭代器it,后可通过*it来访问 */
举例:
vector<int> vi;
for(int i = 1; i <=5; i++){
  vi.push_back(i); //在vi末尾添加元素
}
vector<int>::iterator it = vi.begin();
   
                            注意vi.begin()为取vi的首元素地址,而it指向这个地址

for(int i = 0; i < 5; i++){
 printf("%d" ,*(it+1));
  }

总结:vi[i] 等价于 (vi.begin()+1)

高级:迭代器实现了两种自加操作,故可改进for循环

for(vector<int>::iterator it = vi.begin(); it != vi.end(); it++){
  printf("%d",*it);
  }

注意:只有在vector和string中,才允许使用vi.begin()+3这种迭代器加上整数的写法

1.3 vector常用函数解析

0.end() 注意是尾元素地址的下一个地址
1.push_back(x)//添加
2.pop_back()//删除vector的尾元素
3.size()//获得vector元素的个数,返回类型为unsigned,不过用%d不会出太多问题
4.clear()//清空所有元素,复杂度O(N)
5.insert(it,x)//向迭代器it插入一个元素x,复杂度O(N),可以更改vector特定位置的值
6.erase(it)//删除迭代器为it处的元素
7.erase(vi.begin(),vi.end())//删除一个区间,等同第4点

1.4 常见用途

  1. 存储数据
  • 元素不确定个数的场合
  • 输出同一行的部分数据,中间用空格隔开——更方便处理最后一个满足条件的数据后不输出额外的空格,先用vector记录所有需要输出的数据,然后一次性输出
  1. 用邻接表存储图
  • 可解决因结点太多而无法使用邻接矩阵的题目、替代指针实现邻接表

2.set

集合,内部自动有序且不含重复元素(默认递增

#include<set>
using namespace std;

2.1 定义与访问

单独定义一个set:
set<typename> name;

set数组的定义:
set<typename> Arrayname[arraysize];

set容器内元素的访问:
set<int>::iterator it;

枚举set容器:
for(set<int>::iterator it = st.begin(); it != st.end();it++){
  printf("%d",*it);
}

注意枚举时不支持 it<st.end()的写法,不支持*(it+1)的访问方式;
访问时只能通过迭代器;

2.2 set常用函数解析

1.insert(x) :将x插入到set容器,O(logN)
2.find(value):返回set中对应值为value的迭代器,O(logN)  
  譬如:set<int>::iterator it = st.find(2);
3.erase(it):删除单个元素,it为对应元素迭代器,O(1)
4.erase(value):删除对应值,O(logN)
5.erase(first,last):左闭右开,O(Last-first)
6.size():O(1)
7.clear():o(N)

2.3 常见用途

应用:去掉重复元素/元素较大且类型非int不能直接开散列

3.string

#include<string>
using namespace std;

3.1定义与访问

string str;
string str = "abcd";
str[i];//通过下标访问
cin>>str;//读入或输出整个字符串
cout<<str;
printf("%s\n",str.c_str()) //用printf输出
string::iterator it = str.begin();//迭代器

3.2 string常见函数

1.operator+=:拼接
2.compare operator:直接使用=!=<<=>>=比较大小,比较规则为字典序
3.length()/size():返回长度,O(1)
4.insert(pos,string):插入字符串,string的开头占据了pos的位置
5.insert(it,it2,it3):将[it2,it3)插入到pos
6.erase(it)
7.erase(first,last)
8.clear()
7.substr(pos,len):返回从pos开始长度为len的子串,O(len)
8.find(str2):当str2是str的子串,返回其第一次出现的位置;若不是,返回string:npos
9.find(str2,pos):从str的pos位置开始匹配str2
10.string::npos :-1或者4294967295
11.replace(pos,len,str2):从pos开始,长度为len的子串替换为str2
12.replace(it1,it2,str2):左闭右开

4.map

映射,将任何基本类型映射到任何基本类型

#include<map>
using namespace std;

4.1 定义与访问

若是字符串到整型的映射,只能使用string不能使用char数组;
map会以键从小到大的顺序自动排序(内部是红黑树)

定义:
map<键类型,值类型> name;
map<set<int>, string> mp;

访问使用下标或者迭代器:
mp<char,int> mp;
mp['c'] = 20;
print("%d",mp['c']);
for(map<char,int>::iterator it = mp.begin();it != mp.end(); it++){
  printf("%c %d\n",it->first,it->second);
 }

4.2 map常用函数

1.find(key):返回指定键的迭代器,O(logN)
2.erase(it):O(!)
3.erase(key):O(logN)
4.erase(first,last)
5.size():O(1)
6.clear():O(N)
7.插入可以使用insert()与pair联用

4.3 常见用途

应用:判断给定数字在一个文件是否出现过?
正常思路:开一个bool型的hashTable[max_size],判断其真值
弊端:数字很大就开不了(几千位)
map思路:将这些数字当成字符串,建立string到int的映射

1.字符串与整数之间的映射
2.判断大整数或者其他类型数据是否存在
3.字符串到字符串的映射

5.queue

队列,先进先出

#include<queue>;
using namespace std;

5.1 定义与访问与函数

定义:
queue<typename> name;

访问:
printf("%d%d\n",q.front(),q.back());//只能这样访问

常见函数:
1.push(X)
2.front(),back()
3.pop()
4.empty():判断是否为空,返回bool值
5.size()

5.2 常见用途

广度优先搜索
注意使用front()和pop(),先用empty()判断是否非空

6.priority_queue

优先队列,底层用堆实现,队首默认优先级最大
头文件与5相同

6.1 定义、访问与函数

定义
priority_queue<typename> name;

访问:
printf("%d\n",q.top())  //注意不同

常用函数:
1.push(X)
2.top()
3.pop()
4.empty()
5.size()

6.2 优先级设置

默认越大的优先级越大

1.基本数据类型:
priority_queue<int> q;
priority_queue<int, vector<int>, less<int> > q;
第二个参数填写的是承载底层数据结构堆的容器,第三个参数是对第一个参数的比较类
less<typename>表示越大的优先级越大,greater<typename>表示越小优先级越大

2.结构体:重载操作符
struct fruit{
    string name;
    int price;
    friend bool operator < (fruit f1, fruit f2){
       return f1.price < f2.price;  
       以价格高的水果优先级高
    }
}
int main(){
  priority_queue<fruit> q;
  f1.name = "桃子”;
  f1.price = ...
  ...
  q.push(f1);
  q.push(f2);
  ...
  cout<<q.top().name <<" "<< q.top().price << endl;
  return 0;
}

另一种方法:在结构体外定义优先级
struct cmp{
  bool operator () (fruit f1, fruit f2){
    return f1.price > f2.price;
    }
} 
priority_queue<fruit,vector<fruit>,cmp> > q;
价格越低的越优先

若结构体数据潘达(出现了字符串或者数组),建议使用引用来提高效率

friend bool operator < (const fruit &f1, const fruit &f2){
   return f1.price > f2.price
}

bool operator () (const fruit &f1, const fruit &f2){
  return f1.price <f2.price
}

6.3 常见用途

贪心问题,对迪杰斯特拉优化
注意使用top()前判断是否为空

7.stack

栈,先进后出

#include<stack>
using namespace std;

stack<int> st;

常用函数
1.push(x);
2.top(x)
3.pop()
4.empty()
5.size()

int size

常见用途:
1.模拟实现递归,防止程序对在栈内存的限制导致程序运行出错(一般来说,程序栈内存空间很小)

8.pair

内部由两个元素的结构体

#include<utility>
using namespace std;
或者
#include<map> map的内部实现需要涉及pair

struct pair {
  typename1 first;
  typename2 second;
};

1.定义
pair<typenmae1,typename2> name;
pair<string,int> p;
pair<sting,int> ("haha", 5);
make_pair("haha",5);

2.访问:按照正常结构体的方式访问
cout<<p.first<<" "<<p.second<<endl;

3.实用函数
比较操作数:先以first大小作为标准,当其相等时判断second的大小;

常见用途:
1.用来代替二元结构体以及构造函数
2.作为map的键值对来进行插入

map<string,int> mp;
mp.insert(make_pair("haha",5));
mp.insert(pair<string,int>("heihei",10));
for(map<string,int>::iterator it = mp.begin()l it !=mp.end(); it++){
  cout<<it->first<< " "<<it->second<<endl;
  }

9 .algorithm头文件常用函数

9.1 max/min/abs/swap/next_permutation/fill

#include<algorithm>
using namespace std;

1.max(x,y)/min(x,y)/abs(整数)

2.swap(x,y)

3.reverse(it,it2):将数组指针在[it,it2)之间的元素或容器的迭代器在其间的元素进行反转
   
   int a[10] = { 10,11,12,13,14,15};
   reverse(a,a+4); //(13,12,11,10,14,15)
   
4.next_permutation(first,last):给出一个序列在全排列中的下一个序列
                   并且在到达全排列的最后一个时会返回false,方便退出循环
    
    int a[10] = {1,2,3};
    do{
      printf("%d%d%d\n", a[0],a[1],a[2]);
      }while(next_permutation(a,a+3));
    输出:123 132 213 231 312 321
  
5.fill(first,last,value):把数组或容器的某一区间赋为一个相同值,
                        可以是数组类型对应范围中的任意值

9.2 sort(f,l,cmp)

sort(首元素地址(必填),尾元素下一个地址(必填),比较函数(非必填));
默认递增,,char数组排序默认字典序

9.2.1 基本类型

int a[6] = {...};
sort(a, a+4);//将a[0]到a[3]从小到大排序

编写比较函数cmp
bool cmp(int a ,int b){
  return a>b;
  }
sort(a,a+4,cmp);

9.2.2 结构体数组

struct node{
  int x,y;
  }ssd[10];
  
bool cmp(node a,node b){
  return a.x>b.x;
  }
bool cmp(node a,node b){
 if(a.x != b.x)  return a.x> b.x;
 else return a.y<b.y;
 }
sort(ssd,ssd+3,cmp);

7.2.3容器

只有vector\string\deque可以使用sort,像set、map这种容器用红黑树进行实现,元素本身有序,不允许使用sort排序

1.vector情况:

bool cmp(int a,int b){
  return a>b;
  }
  
  vector<int> vi;
  vi.push_back(3);
  vi.push_back(1);
  vi.push_back(1);
  sort(vi.begin() , vi.end() , cmp);


2.string数组情况
bool cmp(string a,string b){
   return a.length() < b.length();
   }
 string str[3] ={"aaa","bbbb","ccccc"};
 sort(str,str+3,cmp);

9.3 lower_bound()与upper_bound()

需要用在有序数组或容器中

lower_bound(first,last,val):
寻找在该范围内第一个值大于等于val的元素位置,返回指针或迭代器
若没有,返回可以插入的位置

int a[10] = {1,2,2,3,3,3,5,5,5,5};
int* lowerPos = lower_bound(a,a+10,-1);//大于等于
int* upperPos = upper_bound(a,a+10,-1) //小于等于
printf("%d,%d\n", lowerPos-a, upperPos-a);
输出:00

查下标——令返回值减去数组首地址
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值