在过去的不知道多少天里,经过了不同版本视频学习,我终于算是磕磕绊绊的将标准模板库的常用容器和模板都过了一遍(撒花★,°:.☆( ̄▽ ̄)/$:.°★。) 由于是随着听课随着写的这篇学习笔记,所以顺序可能与官方版本不太一样~而且只是我平常会用到的,所以肯定也不会太全
咳咳接下来就是我这些天的学习小结啦!(依照头文件分类)
头文件①:#include"algorithm"
1.sort
sort函数采用的是改进版快排的排序方式,其时间复杂度是nlog(n).
用法有以下三种:
① 最基本的排序用法:sort(数组名+n1,数组名+n2);
注意:sort的排序区间是左闭右开的,不要越界
其效果就是将区间内元素的从小到大的排序
例:
int a[5]={2,0,1,3,4}
sort(a,a+5);
则输出的就是:0,1,2,3,4
② 逆序排序:sort(数组名+n1,数组名+n2,greater<>());
其中尖括号内是需要排序的对象的类型,例如:int,long,double等等
其效果就是令区间内所有元素从大到小排序
③自定义排序方式!:sort(数组名+n1,数组名+n2,自定义排序名称);
顾名思义,可以自定义排序的规则。
例:
struct RULE//按位从小到大排序
{
bool operator()(const T &a1,const T &a2) const{
return a%10<a2%10;
}
};
2.二分查找
注意:用该模板是需要满足条件:必须是排好序的!
①binary_search
用法一:binary_search(数组名+n1,数组名+n2,值)
其区间范围同sort一样也是左闭右开的。其中括号内第三个元素表示要在区间内所要找到的值。如果找到true,反之则返回false。
例:(输入一个数,若能找到就输出yes,否则输出no)
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[5] = { 0,1,2,3,4 };
int n;
cin >> n;
int k=binary_search(a, a + 5, n);
if (k)
cout << "yes";
else
cout << "no";
return 0;
}
用法二:binary_search(数组名+n1,数组名+n2,值,自定义排序名)
注意:如果排序规则与查找规则不同的话,则会查找失败哦!
例:
如果一个数组是按从小到大排的话,自定义排序类型也应该是从小到大排
②lower_bound
用法一:lower_bound(数组名+n1,数组名+n2,值)
俗称二分查找下界:即指向区间内下标最小的,大于等于目标值的元素,并返回其指针。
用法二:lower_bound(数组名+n1,数组名+n2,值,自定义排序名)
其使用方法与之前的sort和binary类似,就不再多说啦!
③upper_bound
用法与lower_bound基本相同,都是返回指针类型,也可以自定义排序规则来进行二分查找,唯一区别是:
upper_bound找的是下标最小的,大于目标值的元素!
头文件②:#include< set >
multiset和set(关联容器)
multiset< > st; (其中尖括号内填数据类型)
一种容器,可以对容器中的元素自动进行排序(初始默认从小到大)可以存放相应类型的数据。
经常使用:
名称 | 作用 |
---|---|
st.insert(); | 添加元素 |
st.find(); | 查找元素 |
st.earse(); | 删除元素 |
st.begin(); | 返回容器中收元素的位置 |
st.end(); | 返回容器中最后一个元素字后的迭代器 |
P.S. 若想要对插入元素的容器进行遍历,需要用到一种迭代器:
muliset< > :: iterator i;(其中尖括号内应与定义容器的类型相同)
近似于指针,它可以进行++,-- , 可以用!=,==比较,但是不能比较谁大谁小,也不能相减,加减整数
例:
#include<iostream>
#include<set>
using namespace std;
int main()
{
multiset<int> st;
int a[5] = { 5,4,2,3,1 };
for (int i = 0; i < 5; i++)
st.insert(a[i]);
multiset<int>::iterator i;
for (i = st.begin(); i != st.end(); i++)
cout << *i <<" ";
return 0;
}
输出就是这个亚子的:
当然了,如果想默认的排序方式不是从小到大,也可以自定义该容器内的排序方式哦,以倒叙为例:
multiset<int,greater<int>()> st;//从大到小排序!!
需要注意的是,在我使用的vs2015中,greater<>模板的使用需要添加头文件#include“functional”
举个栗子:
#include<iostream>
#include<set>
#include<cstring>
#include<functional>
using namespace std;
int main()
{
multiset < int, greater<int>> st;//实现从大到小排序嗷!!!
int a[5] = { 5,4,2,3,1 };
for (int i = 0; i < 5; i++)
st.insert(a[i]);
multiset<int,greater<int>>::iterator i;
for (i = st.begin(); i != st.end(); i++)
cout << *i <<" ";
return 0;
}
然后就变成这个亚子了:
顺便说一句,给数组初始化然后再插入再排序的速度是远慢于输入之后插入再排序的。
讲完了multiset接下来说set
这两者唯一的区别就在于set中的元素是互不相同的,而multiset中可以出现重复元素!!
就拿简单的排序去重问题来举个栗子:
数组的排序去重
资源限制
时间限制:1.0s 内存限制:512.0MB
问题描述
输入10个整数组成的序列,要求对其进行升序排序,并去掉重复元素。
输入格式
10个整数。
输出格式
多行输出,每行一个元素。
样例输入
2 2 3 3 1 1 5 5 5 5
样例输出
1
2
3
5
用set插入数组数据可以直接进行排序去重(因为重复元素会被直接删掉)
code:
#include<iostream>
#include<set>
using namespace std;
int main()
{
set < int> st;
int a[11];
for (int i = 0; i < 10; i++)
cin >> a[i];
for (int i = 0; i < 10; i++)
st.insert(a[i]);
set<int>::iterator i;
for (i = st.begin(); i != st.end(); i++)
cout << *i << endl;
return 0;
}
这是最开始我使用的基础排序去重的数据:
这是使用set直接排序去重(完全不用动脑子)之后的数据:
不仅代码长度变长了,而且cpu的使用,占用的内存都有了显著提升呢!
这都不是重点,重点是开拓了思维,随着不断的学习,一题可以有许多解答方法!!
头文件③:#include< map >
multimap和map(关联容器)
multimap,map容器中的所有元素都是pair形式的!!!
何为pair形式?
pair< , > 尖括号中要有两个变量,可以是相同类型,也可以是不同的。
来来来,举个栗子:
pair< int , double>a;
等价于:
struct a{
int first;//关键字
double second;
};
注意了!!结构体中的变量名一定是first,second,引用方法跟结构体一样。
multimap,map具体用法和multiset,set类似,具体实例以后补充
map依旧是不能出现重复元素!
头文件④:#include< vector >
vector(顺序容器)
可变长动态数组!!!
一维动态数组定义:vector< int > a;
二维动态数组定义:vector<vector< int >> test
容器的初始化:
成员函数 | 作用 |
---|---|
vector(); | 初始化为空 |
vector(int n); | 将其初始化成有n个元素 |
vector(int n,const T &val); | 将其初始化成有n个元素,且值均为val |
然后是常用函数!!!(超级方便,速度快):
函数 | 作用 |
---|---|
pop_back | 尾部元素弹出 |
push_back(); | 尾部插入元素 |
T & front(); | 返回容器第一个元素的引用 |
T & back(); | 返回容器最后一个元素的引用 |
.empty | 判断是否为空 |
.clear | 清空数组 |
当然insert,size,earse等都可以使用。
头文件⑤:#include< list >
list(顺序容器)(双向链表)
定义:list< T > cl;
不支持完全随机访问迭代器!!只能使用双向迭代器,不支持比较运算符,下标随即移动,不支持STL内的函数
但是它也自带许多函数:
sort:排序!:无参cl.sort(); 默认从小到大排,也可以cl.sort(rule); 自定义排序规则
push_front和pop_front: 在链表最前面插入和弹出元素,参考尾插尾弹
remove和unique: remove();删除链表中与括号内指定值相等的所有元素,unique();是删除与前一个元素相等的所有元素(要排序)
merge和reverse:合并两个链表并清空,reverse是颠倒链表!
splice: 在指定位置前面插入另一链表的一个或多个元素,并把另一个链表的相应元素删除掉
头文件⑥:include< deque >
deque(顺序容器)(双向队列)
满足所有vector的操作,还加入了front_push,front_pop操作。
略略略~
以上就是学习笔记了,具体应用后续可能会补充(如果遇到能用的题的话)
虽然我很弱,但是我会努力的(小声嘀咕)