C++ STL 常用函数

vector 常用函数

  • 构造函数

    这里的技巧还是挺多的,但容易忽略

    vector<type> v,默认初始化,大小为0,适合不知道元素个数的情况;

    vector<type> v(v1)vector<type> v = v1,拷贝一份来构造,vv1具有相同的元素;

    vector<type> v = {value1, value2, ...}vector<type> v {value1, value2, ...},用已知元素初始化;

    vector<type> v(number),指定空间为number,每个元素进行缺省的值初始化。对于int,也就是被赋值为0。当程序运行初期元素大致数量可预知,而元素的值需要动态获取的时候,可采用这种初始化方式;

    vector<type> v(number, value),还是指定空间为number,只不过这number个元素都初始化为value

  • 二维 vector 的初始化

    vector < vector <int> > v,默认;

    vector < vector <int> > v(v_d2),用二维vectorv_d2来初始化v

    vector < vector <int> > v(rownum, vector_),第一个参数的含义是“有多少个子vector”,第二个参数表示每个子vector是什么样的。第二个参数可以传入上面讲到的构造一维vector的任何形式。比如:vector < vector <int> > v(rownum, vector <int> (colnum))表示一个全部元素为0的rownumcolnum列的二维vector,或者直接理解为二维数组;再比如vector < vector <int> > v(rownum, vector <int> (colnum, 10))就是将这个二维vector再初始化为10。

  • 访问

    v[idx]v.front()v.back(),访问索引为idx的元素,访问第一个元素,访问最后一个元素。

  • 插入与删除

    v.push_back (value),在vector末尾添加一个元素value

    v.insert (iter, value),在迭代器位置添加元素value

    v.pop_back (),删除vector末尾元素;

    v.erase(iter),删除迭代器位置的元素。

  • 翻转、排序、获取最大值最小值元素

    这些函数所在头文件为algorithm,而不是vector

    reverse(v.begin(), v.end()),翻转。

    sort(v.begin(), v.end()),排序,也可以传入cmp

    max_element(v.begin(), v.end())min_element(v.begin(), v.end())分别表示获取最大值和最小值对应的迭代器,所以一般我们都在前面加上*,直接获取元素值。

    另外,由于vector和string可以采用*(iter+1)的方式进行访问(其他STL不行),所以可以出现部分翻转和部分排序,比如reverse(v.begin(), v.end())sort(v.begin()+1, v.end())*max_element (v.begin(), v.end()-1)等。

  • 常见的函数

    size()empty()clear()

string 常用函数

  • 构造函数

    这里的技巧还是挺多的,但容易忽略

    string s:空串;

    string s(str):与str一样的串;

    string s(str, pos, number):相当于取str从索引pos开始的number个字符的子串进行初始化;如果不传入number则取到str末尾(这完全就是substr后再赋值嘛)

    string s(number, ch):用number个字符ch进行初始化。

  • 字符串长度

    .size().length()(我比较喜欢前者,因为前者输入的字符少~)

  • 获取最后一个位置的字符

    s.back()

  • 大小写转换

    转换为大写:transform (s.begin (), s.end (), s.begin (), ::toupper)
    转换为小写:transform (s.begin (), s.end (), s.begin (), ::tolower)

    也可以遍历字符串,对每个字符进行s[i] = tolower(s[i])的操作来转为小写。

  • 查找

    未查找到:s.find ('a') == string::npos,返回1表示未找到,返回0表示找到了

    从索引为i处开始查找:s.find ('a', i),若找到,返回所在索引位置,没找到返回string::npos

    当然,也可以查找是否包含某个子串。

  • 获取子串

    s.substr (pos, number),从索引为pos的位置开始向后截取number个元素(含pos
    s.substr (pos),从索引为pos的位置开始向后截取到末尾

  • 删除字符或字符串

    s.erase(pos, number),从索引为pos的位置开始向后删除number个元素(含pos
    s.erase(pos),从索引为pos的位置开始向后删除到末尾

  • 插入字符串

    s.insert (pos, str),将str的首字符放在spos位置,其余字符后移。str只能是字符串不能是字符。

  • 部分替换

    s.replace(pos, number, str),将子串s[pos~pos+number-1]的位置全部换成字符串str

    另一种传参形式为s.replace(pos, number, n, ch)等价于s.replace(pos, number, string(n, ch))

  • .c_str()的用法

    将string(C++)转换为char *(C),常见的两个用法:
    printf(%s, s.c_str())atoi(s.c_str())

  • 字符串比较大小

    如果题目要求按字典序排序,则直接通过操作符><=等进行比较大小即可。但有时候我们可能是比较字符串对应的数的大小,那么我们要先判断两个字符串长度,如果不相等,则长者大,如果相等,则再比较字典序。当然也可以先转换为数字(atoi等)再比较。

    还有个很np的compare函数,因为记太多容易混,所以其功能完全可以通过上面讲的函数来代替。

map 常用函数

只讲一下遍历:for (auto item : m) cout << item.first << ' ' << item.second << endl; ,当然也可以使用迭代器。

其他用法与unordered_map一样,见下面。

unordered_map 常用函数

实际操作中,感觉和map没有什么区别,除了遍历方式不同之外,遍历的顺序和map一样都是无序的。据说unordered_map 查找的效率更高些。如果真是这样的话,在比赛时,我们完全可以用unordered_map代替map。
注意,如果已经存在键为key的键值对了,那么再insert是不会覆盖之前插入的键值对的。同样地,初始化过后也无法覆盖,可以先erase后再insert,也可以直接通过中括号访问并赋值。

  • 遍历与访问

    必须通过迭代器,而不能通过for (auto item : m)了,这是与的不同之处。但是也是通过中括号中的键访问对应的值。

    for (auto it = m.begin();it != m.end();it ++) 
    	cout << it->first << ' ' << it->second << ' ' << m[it->first] << endl;
    
  • .empty().size()

  • 初始化与插入

    与map初始化一样,也是unordered_map<int, int> m = {{1, 2}, {5, -1}, {-1, 0}};

    m.insert({key, value})与map也一样。

  • 查找

    m.find (key),返回以key为键的键值对对应的迭代器,如果没有找到,则返回m.end()。注意,如果不先判断是否等于end(),而直接find不会报错,而是会输出缓存中保存的值,所以一定小心。

    如果不要求获取位置,我们更常用的是m.count(key)来判断是否存在,有就返回1,没有就返回0;这个函数的意思是返回键为key的键值对个数,但好像最多就是1。

  • 删除

    m.erase(key),从unordered_map中将以key为键的键值对删除。
    m.clear(),清空全部键值对。

set 常用函数

set最大的一个特点就是自动排序,无论按什么顺序插入,顺序遍历的时候总是按照从小到大的顺序输出。这一特点在有些题中会起到很方便的作用。
unordered_set和set的区别与unordered_map与map的区别类似,但是由于上面讲到的set自动排序的特点,使得set还比较常用。

  • 初始化与插入

    set<type> s = {value1, value2, ...}
    s.insert(value)

  • 查找

    s.find (value),返回value所在迭代器,没找到返回s.end()

  • 删除

    s.erase (value),删除value

    s.erase (begin, end)beginend分别为左端点和右端点对应的迭代器,仍然是左闭右开原则,删除区间内的元素。

  • 另外一些常见的函数

    s.size()
    s.clear()

unordered_set 常用函数

不再赘述,与set类似。

auto 巧用

  • 定义迭代器的时候往往需要很麻烦的写上迭代器的类型,但是我们可以直接使用auto定义:auto it = s.begin ()

其他

  1. 手写cmp函数,如果存在默认排序方式,则可以直接使用greater<type>()less<type>()来代替cmp,这俩函数是采用type升序和降序默认的排序方式。

  2. 有关lower_boundupper_bound

    这俩函数我理解了好久才感觉勉强理解了。

    升序序列中,lower_bound会找出序列中第一个大于等于x的数,upper_bound会找出序列中第一个大于x的数。

    降序序列中,lower_bound会找出序列中第一个小于等于x的数,upper_bound会找出序列中第一个小于x的数。

    所谓“第一个”都是指序列从左到右的第一个。

    使用方法:

    升序序列中,lower_bound (a, a+n, x) - aupper_bound (a, a+n, x) - a得到的是索引;
    降序序列中,lower_bound (a, a+n, x, greater<int>() ) - aupper_bound (a, a+n, x, greater<int>() ) - a得到的是索引;

    一定要注意并不是说只要加了greater<int>(),这俩函数找的就是小于关系的索引。加上这句话后找小于关系一定要保证序列降序!同样地,不加这句话,那就一定要保证升序!否则必然不对。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不牌不改

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值