vector
1.向量(Vector)是一个封装了动态大小数组的顺序容器。跟任意其它类型容器一样,它能够存放各种类型的对象。简单地说,vector是一个能够存放任意类型的动态数组。
#include <vector>
using namespace std;
创建的方法有很多
vector<vector<int>> dp(n + 1, vector<int>(m + 1));//创建一个二维向量,(n + 1) * (m + 1)
最常见的 std::vector<double> values;//如果程序中已经默认指定了 std 命令空间,这里可以省略 std::
vector<double> values(20);//values 容器开始时就有 20 个元素,它们的默认初始值都为 0。
vector<double> values(20, 1.0);//第二个参数指定了所有元素的初始值,因此这 20 个元素的值都是 1.0。
//值得一提的是,圆括号 () 中的 2 个参数,既可以是常量,也可以用变量来表示
int array[]={1,2,3};
std::vector<int>values(array, array+2);//values 将保存{1,2}
std::vector<int>value1{1,2,3,4,5};
std::vector<int>value2(std::begin(value1),std::begin(value1)+3);//value2保存{1,2,3}
包含的成员函数
重要的加粗了加红
$\color{red}{begin() 返回指向容器中第一个元素的迭代器。}$
$\color{red}{end() 返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 begin() 结合使用}$
$\color{red}{size() 返回实际元素个数。}$
$\color{red}{empty() 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。}$
$\color{red}{front() 返回第一个元素的引用。
back() 返回最后一个元素的引用。}$
$\color{red}{push_back() 在序列的尾部添加一个元素。
pop_back() 移出序列尾部的元素。
insert() 在指定的位置插入一个或多个元素。
erase() 移出一个元素或一段元素。
clear() 移出所有的元素,容器大小变为 0。
swap() 交换两个容器的所有元素。
。}$
$\color{red}{ emplace() 在指定的位置直接生成一个元素。
。}$
emplace_back() 在序列尾部生成一个元素
swap() 交换两个容器的所有元素
erase() 移出一个元素或一段元素。
clear() 移出所有的元素,容器大小变为 0。
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//初始化一个空vector容量
vector<char>value;
//向value容器中的尾部依次添加 S、T、L 字符
value.push_back('S');
value.push_back('T');
value.push_back('L');
//调用 size() 成员函数容器中的元素个数
printf("元素个数为:%d\n", value.size());
//使用迭代器遍历容器
for (auto i = value.begin(); i < value.end(); i++) {
cout << *i << " ";
}
cout << endl;
//向容器开头插入字符
value.insert(value.begin(), 'C');
cout << "首个元素为:" << value.at(0) << endl;
return 0;
}
C++ Stack
(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,——也就是说实现了一个先进后出(FILO)的数据结构。
c++ stl栈stack的头文件为:
#include <stack>
c++ stl栈stack的成员函数介绍
操作 比较和分配堆栈
empty() 堆栈为空则返回真
pop() 移除栈顶元素 (删除)
push() 在栈顶增加元素 (增加)
size() 返回栈中元素数目
top() 返回栈顶元素,不删除(获取)
queue
queue 模板类的定义在<queue>头文件中。
queue 模板类也需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为
deque 类型。
定义queue 对象的示例代码如下:
queue<int> q1;
queue<double> q2;
queue 的基本操作有:
入 队:q.push(x); // 将x 接到队列的末端。
出 队:q.pop(); //弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问队首元素:q.front(); //即最早被压入队列的元素。
访问队尾元素:q.back(); //即最后被压入队列的元素。
判断队列空 q.empty(); //当队列空时,返回true。
队列中的元素个数:q.size();
#include<iostream>
#include<queue>
using namespace std;
int main()
{
queue<int> myq;
myq.push(9);
myq.push(3);
myq.push(2);
cout<<"myq.size: "<<myq.size()<<endl;
cout<<myq.front()<<endl;
cout<<myq.back()<<endl;
return 0;
}
priority_queue
和队列基本操作相同:
top 访问队头元素
empty 队列是否为空
size 返回队列内元素个数
push 插入元素到队尾 (并排序)
emplace 原地构造一个元素并插入队列
pop 弹出队头元素
swap 交换内容
定义:priority_queue<Type, Container, Functional>
Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,
比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,
使用基本数据类型时,只需要传入数据类型,默认是大顶堆
一般是:
//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;
//greater和less是std实现的两个仿函数(就是使一个类的使用看上去像一个函数。
其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了)
eg:priority_queue<PII, vector<PII>, greater<PII>> heap; // 定义一个小根堆
set
set
#include <set> using namespace std;
1.概述
set 容器内的元素会被自动排序,set 中的元素即是键值又是实值,set 不允许两个元素有相同的键值。不能通过 set 的迭代器去修改 set 元素,原因是修改元素会破坏set的组织
2.set<int> a; // 定义一个int类型的集合a
// set<int> a(10); // error,未定义这种构造函数
//set<int> a(10, 1); // error,未定义这种构造函数
set<int> b(a); // 定义并用集合a初始化集合b
set<int> b(a.begin(), a.end()); // 将集合a中的所有元素作为集合b的初始值
3.查找键 key 的元素个数:st.count(key);
4.在容器中插入元素:st.insert(const T& x);
任意位置插入一个元素:st.insert(iterator it, const T& x);
5.删除容器中值为 elem 的元素:st.pop_back(const T& elem);
删除it迭代器所指的元素:st.erase(iterator it);
删除区间 [first,last] 之间的所有元素:st.erase(iterator first, iterator last);
清空所有元素:st.clear();
6.查找键 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end(): st.find(key);
7.交换两个同类型容器的元素:swap(set&, set&);或lst.swap(set&);
8.可以看到,set 与序列式容器的用法有以下几处不同:
set 不支持 resize() 函数;
set 容器不提供下标操作符。为了通过键从 set 中获取元素,可使用 find 运算;
set 只能使用insert的两种重载函数插入,不支持 push_back()和push_front() 函数;
set 不支持 STL 里的 reverse 和 sort 算法;
set 能不通过迭代器,只通过元素值来删除该元素;
set 只支持默认构造函数和拷贝构造函数,没有其它重载的构造函数。
set 遍历
#include<iostream>
#include<set>
using namespace std;
set<int>all;
int main()
{
//生成待处理的数据
for(int i=0;i<100;i++)
all.insert(i);
//遍历set,用迭代器类型
for(set<int>::iterator i=all.begin();i!=all.end();i++)
cout<<*i<<endl; //注意指针运算符
return 0;
}
c++中map与unordered_map的区别
头文件
map: #include < map >
unordered_map: #include < unordered_map >
内部实现机理
map: map内部实现了一个红黑树,该结构具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素,因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行这样的操作,故红黑树的效率决定了map的效率。
unordered_map: unordered_map内部实现了一个哈希表,因此其元素的排列顺序是杂乱的,无序的
优缺点以及适用处
map
优点:
有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作
红黑树,内部实现一个红黑书使得map的很多操作在lgnlgn的时间复杂度下就可以实现,因此效率非常的高
缺点:
空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为
每一个节点都需要额外保存父节点,孩子节点以及红/黑性质,使得每一个节点都占用大量的空间
适用处,对于那些有顺序要求的问题,用map会更高效一些
`unordered_map`
优点:
因为内部实现了哈希表,因此其查找速度非常的快
缺点:
哈希表的建立比较耗费时间
适用处,对于查找问题,`unordered_map`会更加高效一些,因此遇到查找问题,常会考虑一下用`unordered_map`
note:
对于unordered_map或者unordered_set容器,其遍历顺序与创建该容器时输入元素的顺序是不一定一致的,遍历是按照哈希表从前往后依次遍历的
map
1,map简介
map是 一个关联容器,它提供一对一的hash。
第一个可以称为关键字(key),每个关键字只能在map中出现一次;
第二个可能称为该关键字的值(value);
#include <map>
// 定义一个map对象
map<int, string> mapStudent;
// 第一种 用insert函數插入pair
mapStudent.insert(pair<int, string>(000, "student_zero"));
// 第二种 用insert函数插入value_type数据
mapStudent.insert(map<int, string>::value_type(001, "student_one"));
// 第三种 用"array"方式插入
mapStudent[123] = "student_first";
mapStudent[456] = "student_second";
//以上三种用法,虽然都可以实现数据的插入,但是它们是有区别的,当然了第一种和第二种在效果上是完成一样的,用insert函数插入数据,在数据的 插入上涉及到集合的唯一性这个概念,即当map中有这个关键字时,insert操作是不能在插入数据的,但是用数组方式就不同了,它可以覆盖以前该关键字对 应的值
4.find
// find 返回迭代器指向当前查找元素的位置否则返回map::end()位置
iter = mapStudent.find("123");
if(iter != mapStudent.end())
cout<<"Find, the value is"<<iter->second<<endl;
5.
//迭代器刪除
iter = mapStudent.find("123");
mapStudent.erase(iter);
//用关键字刪除
int n = mapStudent.erase("123"); //如果刪除了會返回1,否則返回0
//用迭代器范围刪除 : 把整个map清空
mapStudent.erase(mapStudent.begin(), mapStudent.end());
//等同于mapStudent.clear()
clear() 删除所有元素
count() 返回指定元素出现的次数, (帮助评论区理解: 因为key值不会重复,所以只能是1 or 0)
empty() 如果map为空则返回truecount函数的功能是:统计容器中等于value元素的个数。
先看一下函数的参数:
count(first,last,value); first是容器的首迭代器,last是容器的末迭代器,value是询问的元素。
string
头文件: # include < cstring >
string str;//定义空 string 容器
string str = "abcde";
string str{ "abcde" };
小括号是复制的作用, 是将"abcde"复制给 str
大括号是赋值的作用, 是给 str 赋值 “abc”
string str1 = str; //定义新容器 str1, 拷贝 str 所有的元素
string str12(str.begin(), str.end());
//定义新容器 str12, 拷贝区间内元素
迭代器
包括:begin、end、rbegin、rend、cbegin、cend、crbegin、crend
使用方法
str.begin(); 返回迭代器, 指向第一元素
str.end(); 返回迭代器, 指向最末元素的下一个位置
str.rbegin(); 返回反向迭代器, 指向反向迭代的第一元素
str.rend(); 返回反向迭代器, 指向反向迭代的最末元素的下一个位置
string str="abcdefghijklmn";
for(auto it=str.begin();it!=str.end();it++){
//注意这里是不等于end, 而不是小于end
cout<<*it<<endl;
}
输出结果为:
abcdefghijklmn
str[id]; 返回下标为 id 的字符, 不检查是否越界
str.assign(str1.begin()+1, str1.end()-1);
//将区间内的元素赋值给 str
1. =:字符串赋值
例: s1为空, 则: s1=“abc"之后, s1变为"abc”
2. +和 +=:连接字符串
用的较多的是 +=
例: s1=“abc”, s2=“123”, 则: s1+=s2之后, s1 变为 “abc123”, s2不变
3.<、>=、< 和 <=:字符串比较 (例如a < b)
按字典序判断字符串的大小, 并返回判断结果.
例: s1=“abc”, s2=“abb”, 则 s1<s2 返回 false
例: s1=“abc”, s2=“abb”, 则 s1>s2 返回 true
4.==、!=:比较字符串
判断字符串是否相同
例: s1=“abc”, s2=“abb”, 则 s1 ==s2 返回 false
5.<<、>>:输出、输入字符串
直接使用cin和cout输出
cin>>str;
cout<<str;
str.swap(str1);
// 交换两个容器的内容
//例:str="abc", str1="123"
//运行之后, str="123", str1="abc"
str.push_back('s');
//在 str 末尾添加字符 's'
//例:str="abc"
//运行之后, str="abcs"
str.pop_back();
//删除最后一个字符
//例:str="abc"
//运行之后, str="ab"
str.front();
//返回第一元素
//例:str="abc"
//str.front()就等于 'a'
str.back();
//返回最末元素
//例:str="abc"
//str.back()就等于 'c'
str.clear();
//清空容器
str.empty();
//容器为空返回 true, 否则返回 false
str.erase(3);
//删除 str[3]~str[n-1] , 返回 str
//例: str="abcabcabc"
//运行之后, str="abc"
str.erase(2, 3);
//删除 str[2]~str[2+3-1] , 返回 str
//删除 str[2] 开始的 3 个字符
//例: str="abcqw123"
//运行之后, str="ab123"
str.erase(str.begin());
//删除指向的元素, 返回迭代器, 指向下一元素
//例: str="abc"
//运行之后, str="bc", 返回指向字符 'b' 的迭代器
str.erase(str.begin(), str.end());
//删除区间内的元素, 返回迭代器, 指向下一元素
//例: str="abc"
//运行之后, str="c", 返回指向字符 'c' 的迭代器
//因为删除的字符是 "ab" 下一个字符是 'c'
//所以返回指向字符 'c' 的迭代器
str.find(ch, 2);
//返回 ch 在 str[2]~str[n-1] 中首次出现的位置
//例: str="abcabc", ch="bc"
//返回 4
eg:
ios::sync_with_stdio(false);
cin.tie(0);
string p, s;
int n, m;
cin >> n >> p >> m >> s;
int i = 0;
while ((i = s.find(p, i)) != s.npos) {
printf("%d ", i);
i++;
}
拷贝相关:
str2=str1.substr(2); //提取子串,提取出str1的下标为2到末尾,给str2
str2=str1.substr(2,3); //提取子串,从 str1的下标为2开始,提取3个字节给str2
1、to_string
包含在# include<string>。作用是把数值类型如int、double、long等转化为string,详细可参考博客:https://blog.csdn.net/lzuacm/article/details/52704931
int a = 4;
double b = 3.14;
string str1, str2;
str1 = to_string(a);
str2 = to_string(b);
cout << str1 << endl;
cout << str2 << endl;
2、stoi和atoi
包含在
#include<string>
,不是c++11的可以在#include<cstring>
。作用是将字符串转化为int型。区别是stoi的形参是const string,而atoi的形参是const char。c_str()的作用是将const string转化为const char。
string s1("1234567");
char* s2 = "1234567";
int a = stoi(s1);
int b = atoi(s2);
int c = atoi(s1.c_str());
cout << a << endl;
cout << b << endl;
cout << c << endl;