vector 常用函数
-
构造函数
这里的技巧还是挺多的,但容易忽略
vector<type> v
,默认初始化,大小为0,适合不知道元素个数的情况;vector<type> v(v1)
或vector<type> v = v1
,拷贝一份来构造,v
和v1
具有相同的元素;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的rownum
行colnum
列的二维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
的首字符放在s
的pos
位置,其余字符后移。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)
,begin
和end
分别为左端点和右端点对应的迭代器,仍然是左闭右开原则,删除区间内的元素。 -
另外一些常见的函数
s.size()
s.clear()
unordered_set 常用函数
不再赘述,与set类似。
auto 巧用
- 定义迭代器的时候往往需要很麻烦的写上迭代器的类型,但是我们可以直接使用auto定义:
auto it = s.begin ()
其他
-
手写
cmp
函数,如果存在默认排序方式,则可以直接使用greater<type>()
或less<type>()
来代替cmp
,这俩函数是采用type
升序和降序默认的排序方式。 -
有关
lower_bound
和upper_bound
这俩函数我理解了好久才感觉勉强理解了。
升序序列中,
lower_bound
会找出序列中第一个大于等于x
的数,upper_bound
会找出序列中第一个大于x
的数。降序序列中,
lower_bound
会找出序列中第一个小于等于x
的数,upper_bound
会找出序列中第一个小于x
的数。所谓“第一个”都是指序列从左到右的第一个。
使用方法:
升序序列中,
lower_bound (a, a+n, x) - a
,upper_bound (a, a+n, x) - a
得到的是索引;
降序序列中,lower_bound (a, a+n, x, greater<int>() ) - a
,upper_bound (a, a+n, x, greater<int>() ) - a
得到的是索引;一定要注意并不是说只要加了
greater<int>()
,这俩函数找的就是小于关系的索引。加上这句话后找小于关系一定要保证序列降序!同样地,不加这句话,那就一定要保证升序!否则必然不对。