C++高效刷题必知必会

前言

总结汇总一下使用c++进行刷题的时候,一些常用的STL容器、算法函数、语言特性、语法糖等。
有助于刷题的时候高效快速进行编码。

迭代器Iterator

定义:迭代器是一种检查容器内元素并遍历元素的数据类型。
迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。

迭代器(Iterator)是指针(pointer)的泛化,指针可以用来遍历存储空间连续的数据结构,但是对于存储空间费连续的,就需要寻找一个行为类似指针的类,来对非数组的数据结构进行遍历,迭代器由此诞生。

迭代器的声明:

//以vector为例
vector<int>::iterator it;//声明一个vector<int>类型的迭代器

字符串类型string

c++内置字符串类型

构造函数:

string str;
string str2(str);//拷贝str的值初始化str2

常用内置函数:

//1、front() 返回首字符
str.front()
//2、back()返回最后一个字符
str.back()
//3、data() 返沪指向字符串首部的指针,(相当于将string转为char[] ,返回数组地址)
str.data()
//4、empty() 字符串为空返回true
str.empty()
//5、size() or length()
str.size()//返回字符串长度
//6、erase()
str.erase(2)//移除第二个字符
str.erase(02)//移除第0-2的字符
str.erase(str.begin(),str.end())//移除所有字符

//7、insert()
str.insert(0,'a')//在第一个字符前面插入a
str.insert(str.beign(),'a')//在第一个字符前面插入a=
str.insert(0,2,'a')//在第一个字符前面插入两个a

//8、push_back() or append()
str.push_back('a') or str.append('a') //末尾添加
//9、pop_back()
str.pop_back()//弹出末尾字符
//10、starts_with
str.starts_with("aa")//是否以“aa”开头
//11、ends_with
str.ends_with("aa")//是否以“aa”结尾

//12、find()
str.find(str1)//在str中查找str1,找到返回起始下标,找不到返回string::npos (-1)
//13、replace()
str.replace("a","b")
//14、substr()获取字符串的子串
str.substr(1,7)//获取从下标为1的字符串开始长度为7的字符串
//15、stoi()字符串转整型
stoi("111")
//16、stol()字符串转长整型
stol("111")
//17、to_string()
to_string(100)

顺序容器

vector

vector以线性排列方式存储给定类型的元素,并允许快速随机访问任何元素。 当随机访问性能处于高级时,向量是序列的首选容器。

template <class Type, class Allocator = allocator<Type>>
class vector

构造方法:

//空向量
vector<int> arr;
//长度为10的整型向量,元素初值为0
vector<int>arr(10);
//长度为10,初值为1
vector<int>arr(10,1);
//使用另一个向量tmp初始化arr
vector<int>arr(tmp);
//使用另一个向量的前三个元素初始化arr
vector<int>arr(b.begin(),b.begin()+3);
//使用数组a的所有元素初始化arr
int a[6]={1,2,3,4,5,6};
vector<int> arr(a,a+6;
//二维数组的初始化
vector<vector<int>> matrix(10,vector<int>(10,1))//初始化10*10的二维数组,元素都为1

常用内置函数:

//1、assign,类似于重新初始化操作
arr.assign(6,6);//给arr赋值为6个值为6的元素
arr.assign(tmp.begin(),tmp.end());//将tmp所有元素赋值给arr

//2、back()
arr.back()//返回最后一个元素
//3、front()
arr.front()//返回第一个元素

//4、push_back()
arr.push_back(element) //给arr的后面追加元素element
//5、pop_back()
arr.pop_back()//弹出,丢弃最后一个元素

//6、clear()
arr.clear()//清空所有元素
//7、empty()
arr.empty()//判断是否为空,为空则true
//8、erase()
arr.erase(arr.begin()+3)//删除第4个元素
arr.erase(arr.begin()+3,arr.end())//删除第四个及以后的所有元素

//9、insert()
arr.insert(arr.begin(),10)//在arr前面增加一个元素10
arr.insert(arr.begin(),tmp.begin(),tmp.end())//将tmp所有元素插到arr前面
//10、size()
arr.size()//返回元素个数

注意:

  • 该模板一般作为数组使用,支持[] 访问元素。
  • 内置函数size() 尽量不要重复反复调用。

list

List是stl实现的双向链表,与向量(vectors)相比, 它允许快速的插入和删除,但是随机访问却比较慢。

template <class Type, class Allocator= allocator<Type>>
class list

构造方法:

    list<int>lst1;          //创建空list

    list<int> lst1(10);       //创建含有10个元素的list,值为0

    list<int>lst1(6,6);  //创建含有6个元素值为6的list

    list<int>lst1(lst2);    //使用lst2初始化lst4

    list<int>lst1(lst2.begin(),lst2.begin()+6);  //使用lst2前6个元素初始化

常用内置函数

//1、assign()
list1.assign(6,6);//给arr赋值为6个值为6的元素
list1.assign(tmp.begin(),tmp.end());//将tmp所有元素赋值给arr
//2、back()
list1.back()//返回最后一个元素 
//3、clear() 
list1.clear() //删除所有元素 
//4、empty()
list1.empty()//链表为空则返回true
//5、erase()
list1.erase(list1.begin()+3)//删除第三个元素
list1.erase(list1.begin(),list1.begin()+4)//删除前4个元素
//6、front()
list1.front()// 返回第一个元素
//7、insert() 
list1.insert(list1.begin()+3,3)// 插入一个元素到list中第三个元素前面 
//8、merge()
list1.merge(list2)// 合并list1和list2
//9、 push_back()
list1.push_back() 在list的末尾添加一个元素 
//10、 push_front()
list1.push_front() 在list的头部添加一个元素 
//11、pop_back()
list1.pop_back() 删除最后一个元素 
//12、pop_front()
list1.pop_front() 删除第一个元素 

//13、resize
list1.resize() //改变list的大小 
//14、reverse()
list1.reverse() //倒转链表
list1.size() 返回list中的元素个数 
//15、sort()
list1.sort()// 给list排序 
//16、unique()
list1.unique() 删除list中重复的元素

deque

有下标顺序容器,它允许在其首尾两段快速插入及删除。另外,在 deque 任一端插入或删除不会非法化指向其余元素的指针或引用。

template <class Type, class Allocator =allocator<Type>>
class deque

构造函数:

deque<int> dq;
//其他参考vector

常用内置函数:

//在vector的基础上增加了:
//push_front()
dq.push_front(element)
//pop_front()
dq.pop_front()

关联容器

Set

集合类容器,有set,unordered_set,multiset

这类容器都有以下的构造方法以及常用函数(以set为例):
构造方法:

set<int> se;
set<int> se(se1);

常用内置函数:

//1、empty()
se.empty()//集合为空则返回true
//2、size()
se.size()//返回元素个数
//3、insert()
se.insert(element)//插入一个元素
//4、erase()
se.erase(element)//删除一个元素
//5、count()
se.count(element)//查询集合中有多少个element,对于set和unordered_set,效果等同于contains
//6、find()
se.find(element)//查询element的位置
//7、contains()
se.contains(element)//判断是否含有该元素
//8、lower_bound()
se.lower_bound(element)//返回指向首个不小于给定键的元素的迭代器
//9、upper_bound()
se.upper_bound(element)//返回指向首个大于于给定键的元素的迭代器
//10、clear()
se.clear()

set

std::set 是关联容器,含有 Key 类型对象的已排序集。用比较函数 比较 (Compare) 进行排序。搜索、移除和插入拥有对数复杂度。 set 通常以红黑树实现。

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key> > class set;

unordered_set

unordered_set 是含有 Key 类型唯一对象集合的关联容器。搜索、插入和移除拥有平均常数时间复杂度。
在内部,元素并不以任何特别顺序排序,而是组织进桶中。元素被放进哪个桶完全依赖其值的哈希。这允许对单独元素的快速访问,因为哈希一旦确定,就准确指代元素被放入的桶。
不可修改容器元素(即使通过非 const 迭代器),因为修改可能更改元素的哈希,并破坏容器。

template<
    class Key,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator<Key>
> class unordered_set;

multiset*

std::multiset 是含有 Key 类型对象有序集的容器。不同于 set ,它允许多个关键拥有等价的值。用关键比较函数 Compare 进行排序。搜索、插入和移除操作拥有对数复杂度。

template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class multiset;

unordered_multiset*

unordered_multiset 是关联容器,含有可能非唯一 Key 类型对象的集合。搜索、插入和移除拥有平均常数时间复杂度。
元素在内部并不以任何顺序排序,只是被组织到桶中。元素被放入哪个桶完全依赖其值的哈希。这允许快速访问单独的元素,因为一旦计算哈希,它就指代放置该元素的准确的桶。

template<
    class Key,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator<Key>
> class unordered_multiset;

经验:
题目有有序的需求的时候,使用set,没有的话可以使用unordered_set,其余两个用的比较少,有需求的时候,自行查找资料,学习详细的使用方法。

Map

哈希map类容器,主要有map,unordered_map,multimap,unordered_multimap
这类容器都有如下的常用构造方法以及内置函数(以map为例):

构造方法:

map<int,int> hash_map;
map<int,int> hash_map(another_map);

常用内置函数:

//1、empty()
hash_map.empty()//
//2、size()
hash_map.size()//
//3、insert()
hash_map.insert({key,value})//插入键值对
//4、erase()
hash_map.erase(key)//删除某个键
//5、count()
hash_map.count(key)//返回匹配特定键的元素数量
//6、find()
hash_map.find(key)//查找给定键的位置,返回迭代器
//7、contains()
hash_map.contains(key)//检查容器是否含有带特定键的元素
//8、lower_bound()
hash_map.lower_bound(key)//返回指向首个不小于给定键的元素的迭代器
//9、upper_bound()
hash_map.upper_bound(key)//返回指向首个大于给定键的元素的迭代器
//10、clear()
hash_map.clear()

注意:
给map中插入元素使用更多的是这种形式:

hash_map[key]=value

map

std::map 是有序键值对容器,它的元素的键是唯一的。用比较函数 Compare 排序键。搜索、移除和插入操作拥有对数复杂度。 map 通常实现为红黑树。

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class map;

unordered_map

unordered_map 是关联容器,含有带唯一键的键-值 pair 。搜索、插入和元素移除拥有平均常数时间复杂度。

元素在内部不以任何特定顺序排序,而是组织进桶中。元素放进哪个桶完全依赖于其键的哈希。这允许对单独元素的快速访问,因为一旦计算哈希,则它准确指代元素所放进的桶。

template<
    class Key,
    class T,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;

multimap*

multimap 是关联容器,含有键值对的已排序列表,同时容许多个元素拥有同一键。按照应用到键的比较函数 Compare 排序。搜索、插入和移除操作拥有对数复杂度。
拥有等价键的键值对的顺序就是插入顺序,且不会更改。

template<
    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >
> class multimap;

unordered_multimap*

unordered_multimap 是无序关联容器,支持等价的关键(一个 unordered_multimap 可含有每个关键值的多个副本)和将关键与另一类型的值关联。 unordered_multimap 类支持向前迭代器。搜索、插入和移除拥有平均常数时间复杂度。
元素在内部不以任何特定顺序排序,而是组织到桶中。元素被放进哪个桶完全依赖于其关键的哈希。这允许到单独元素的快速访问,因为哈希一旦计算,则它指代元素被放进的准确的桶。

template<
    class Key,
    class T,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_multimap;

经验:
题目有有序的需求的时候,使用map,没有的话可以使用unordered_map,其余两个用的比较少,有需求的时候,自行查找资料,学习详细的使用方法。

容器适配器

stack

template <class Type, class Container= deque <Type>>
class stack

构造方法:

stack<int> stk;

常用内置函数:

stk.empty() //堆栈为空则返回真

stk.pop() //弹栈

stk.push() //入栈

stk.size() 返回栈中元素数目

stk.top() 返回栈顶元素

queue

template <class Type, class Container = deque <Type>>
class queue

构造方法:

queue<int> que;

常用内置函数:

que.empty() //堆栈为空则返回真

que.pop() //弹出队列首部

que.push() //入队列

que.size() 返回队列中元素数目

que.front() 返回栈顶元素

priority_queue

优先队列,使用该类构造来满足需求

template <class Type, class Container= vector<Type>, class Compare= less <typename Container ::value_type>>
class priority_queue
// Type:元素类型

//Container:容器类型,默认为vector,一般不动

//Compare:元素的比较方式,决定是最大堆还是最小堆,默认最大堆

构造方法:

priority_queue<int> pq;

常用内置函数:

//1、top()
pq.top()//返回堆顶元素
//2、push()
pq.push(element)//往堆中添加元素
//3、size()
pq.size()//返回元素个数
//4、pop()
pq.pop()//弹出堆顶元素
//5、empty()
pq.empty()//堆为空则true

关于比较器

当元素类型是基本类型的时候(intfloatdouble...)
自定义最大最小堆使用less<type> 和greater<type>:

priority_queue<int,vector<int>,less<int>> pq;//最大堆,可省略容器和比较器的指定
priority_queue<int,vector<int>,greater<int>> pq;//最小堆

当元素类型是自定义类型的时候,需要自定义比较器:
今有如下自定义类型Node
struct Node{
	int val;
};

自定义比较器,比较器内部重载()运算符:
struct cmp{
	bool operator() (Node* a,Node* b){
		return a.val < b.val; //这个是生成最大堆,也就是降序,反之最小堆,升序
	}
}

priority_queue<Node*,vector<Node*>,cmp> pq;

pair

template<
    class T1,
    class T2
> struct pair;

其实就是只有两个元素的结构体。
声明:

pair<TYPE1,TYPE2> pa;
pair<int,string> pa;

元素访问:

int ele=pa.first//访问第一个元素
string str=pa.second//第二个元素

int ele=get<0>(pa)//访问第一个元素
string str=get<1>(pa)//第二个元素

int ele=get<int>(pa)//访问第一个元素
string str=get<string>(pa)//第二个元素

内置函数:

//1、make_pair
pair<int,string> pa=make_pair(1,"a");

tuple

template< class... Types >
class tuple;

类模板 std::tuple 是固定大小的异类值汇集。它是 std::pair 的推广。
声明:

tuple<TYPE1,TYPE2,TYPE3,...> tup;
tuple<int,string,double,...> tup;

元素访问:

int ele=get<0>(tup)//访问第一个元素
string str=get<1>(tup)//第二个元素

int ele=get<int>(tup)//访问第一个元素
string str=get<string>(tup)//第二个元素

内置函数:

//1、make_pair
tuple<int,string,douple> tup=make_tuple(1,"a",1.001);

算法

最大最小操作

max:

int a=10,b=11;
int c=max(a,b);

max_element:

//1、数组则返回指针
int a[10];
int* max_one=max_element(a,a+10);
//2、stl则返回迭代器
vector<int> arr;
vector<int>::iterator max_one=max_element(arr.begin(),arr.end());

min:

int a=10,b=11;
int c=min(a,b);

min_element:

//1、数组则返回指针
int a[10];
int* max_one=min_element(a,a+10);
//2、stl则返回迭代器
vector<int> arr;
vector<int>::iterator max_one=min_element(arr.begin(),arr.end());

排序

数组排序:

int a[10];
sort(a,a+10,cmp)

stl排序:

vector<int> arr;
sort(a.begin(),a.end(),cmp)

自定义比较规则:

bool cmp(int a,int b){
	return a>b;//降序
}

二分

lower_bound:
找到第一个大于等于target的元素的地址。

//1、数组
int* ptr=lower_bound(a,a+10,target);
int* ptr2=lower_bound(a,a+10,target,cmp);
//2、stl
vector<int>::iterator it1=lower_bound(arr.begin(),arr.end(),target);
vector<int>::iterator it2=lower_bound(arr.begin(),arr.end(),target,cmp);

upper_bound:
找到第一个大于target的元素的地址。

//1、数组
int* ptr=upper_bound(a,a+10,target);
int* ptr2=upper_bound(a,a+10,target,cmp);
//2、stl
vector<int>::iterator it1=upper_bound(arr.begin(),arr.end(),target);
vector<int>::iterator it2=upper_bound(arr.begin(),arr.end(),target,cmp);

数值转换

数字转字符串

to_string:

to_string(1);
to_string(1.01);
to_string(-111111111);

字符串转数字

stoi("111");//int
stol("1111");//long
stoll("1111");//long long


stof("1.01");//float
stod("1.01");//double

逆转元素顺序

int a[10];
reverse(a,a+10);

vector<int> arr;
reverse(arr.begin(),arr.end());

其他

auto

这个类型可以根据等式右边自动识别类型。

auto a=10;
auto it=arr.begin();

//使用auto接tuple类型
auto tup=make_tuple(1,"a",2);
auto [a,b,c]=make_tuple(1,"a",2);

元素的遍历

搭配auto的map的遍历:

map<int,string> hash_map;
for(auto& [k,v] : hash_map){
	
}

其他类型:

vector<int> arr;
for(auto& e : arr){

}

lambda表达式

一般用来替代函数。
语法 :

auto fun1=[](Type type1,Type type2,...)->ReturnType{
	//TODO--
	return returnValue;
} 

例子:
应用于排序替代自定义比较函数:

int a[10];
sort(a,a+10,[](int a,int b)->bool{
	return a>b;
});

总结

上面介绍的只是各个知识点冰山一角,还有很多更丰富更奇特的用法,读者可以自己查资料。

谢谢。

  • 10
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值