Random notes, for reference only
Data structures in C++
- Header files that need to be imported
- Array (vector) -- vector
-
- object definition method
- ordinary definition
- vector operations
-
-
- `push_back` inserts at the end
- `emplace_back` is constructed at the end
- `pop_back` is deleted at the end
- back() gets the tail element
- front() gets the head element
- The number of size elements
- insert(i,x) insert before i
- Insert--merge vector
- delete --erase
- Get the first element reference front and the last element reference back
- resize(n, value) Modify size
- array flip
- copy vector
-
- Algorithm
- Queue --- queue
- Stack ---Stack
- heap
- priority queue
- Hash table
- gather
- for loop
- Array assignment memset
- key-value pair
- tuple tuple
- string string
-
-
-
- Basic operations
- Case conversion
- substr finds substring
- string => const char*
- Character deletion erase
- Character operations
- String splitting
- Character search
- String comparison compare
- char* => int
- string => int, double, long, long long ...
- int => string
- char=>string
- character stream stringstream
- Determine whether a string is a letter isalpha
-
-
- anonymous function
- decltype keyword
Header files that need to be imported
#include <iostream>
#include <vector> // vector
#include <algorithm> // find, swap, sort, unique, reverse, lower_bound, min, max, max_element
#include <functional> // less, greater
#include <queue> // priority_queue, queue
#include <stack> // stack
#include <unordered_map> // unordered_map
#include <unordered_set> // unordered_set
#include <map> // map, multimap
#include <set> // set, multiset
#inlcude <utility> // pair, swap(exchange values of two objects)
#include <tuple> // tuple (get)
#include <string> // string
using namespace std;
sum of two numbers
Enter description
输入数据有多组, 每行表示一组输入数据。
每行不定有n个整数,空格隔开。(1 <= n <= 100)。
Output description
每组数据输出求和的结果
Example:
Import:
1 2 3
4 5
0 0 0 0 0
Output:
6
9
0
Code:
#include <iostream>
#include <vector>
using namespace std;
using ll = long long;
int solution(vector<int>& nums){
int n = nums.size();
ll sum = 0;
for(int i=0;i<n;i++){
sum += nums[i];
}
return sum;
}
void submit(int ans){
cout << ans << endl;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int n;
vector<int> nums;
while(cin >> n){
nums.push_back(n);
if(cin.get() == '\n'){
int ans = solution(nums);
submit(ans);
nums.clear();
}
}
return 0;
}
// 64 位输出请用 printf("%lld")
Sort the input string
Enter description
多个测试用例,每个测试用例一行。
每行通过,隔开,有n个字符,n<100
Output description
对于每组用例输出一行排序后的字符串,用','隔开,无结尾空格
Example
Import:
a,c,bb
f,dddd
nowcoder
Output:
a,bb,c
dddd,f
nowcoder
Code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
using ll = long long;
vector<string> solution(vector<string>& nums){
int n = nums.size();
sort(nums.begin(), nums.end());
return nums;
}
void submit(vector<string>& ans){
int n = ans.size();
for(int i=0;i<n;i++){
cout << ans[i];
if(i != n-1){
cout << ",";
}
}
cout << endl;
}
void split(string& s, vector<string>& tokens, const string& delimiters=" "){
auto last_pos = s.find_first_not_of(delimiters, 0);
auto pos = s.find_first_of(delimiters, last_pos);
while(pos!=string::npos || last_pos !=string::npos){
tokens.push_back(s.substr(last_pos, pos-last_pos));
last_pos = s.find_first_not_of(delimiters, pos);
pos = s.find_first_of(delimiters, last_pos);
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
string a;
while(getline(cin, a)){
vector<string> nums;
split(a, nums, ",");
auto ans = solution(nums);
submit(ans);
}
return 0;
}
// 64 位输出请用 printf("%lld")
Array (vector) -- vector
#include <vector>
object definition method
//一维vector
vector<int> *v = new vector<int>();
//二维vector
vector<vector<int>> *v2 = new vector<vector<int>*>();
Traverse
//打印输出(二维数组)
for(int i=0;i<v2->size();i++){
for(int j=0;j<v2->at(0)->size();j++){
cout << v2->at(i)->at(j) << endl;
}
}
ordinary definition
//声明R行C列的数组,赋初值为0
vector<vector<int>> flag(R, vector<int>(C, 0));
Declaration of vector with dimensions (n,2)
The first:
vector<vector<int>> cp(n,vector<int>(2,0));
for(int i=0;i<n;i++){
cp[i][0] = capital[i];
cp[i][1] = profits[i];
}
The second type:
vector<vector<int>> cp(n);
for(int i=0;i<n;i++){
// cp[i].emplace_back(capital[i]);
// cp[i].emplace_back(profits[i]);
cp[i].push_back(capital[i]);
cp[i].push_back(profits[i]);
}
Logic aboveemplace_back()
Good point.
ExistingIn this example, push_back()
Small ratioemplace_back()
Good point.
Third type:
vector<pair<int,int>> cp;
for(int i=0;i<n;i++){
// cp[i] = {capital[i],profits[i]};
cp.push_back({
capital[i],profits[i]});
}
The third method is the fastest, the second is the second, and the first is the slowest.
vector<pair<int,int>>
is twice as fast as vector<vector<int>>
.
vector operations
push_back
Insert at the end
void push_back(const T& x): Add an element X to the tail of the vector
emplace_back
Construct at the tail
push_back()
When adding an element to the end of the container, it will firstcreate this element, and then add this element Copy or move into the container (if copied, the previously created element will be destroyed afterwards) < When /span>The process of copying or moving elements saves Go directly at the end of the container, creates the element
emplace_back()
is implemented,
pop_back
Delete at the end
void pop_back(): delete the last element in the vector
back() gets the tail element
v.back()
front() gets the head element
v.front()
The number of size elements
int size() const: returns the number of elements in the vector
insert(i,x) insert before i
iterator insert(iterator i,x)
A.insert(A.begin()+k,x)
Insert – merge vector
//在A的后面插入
A.insert(A.end(),B,begin(),B.end());
delete –erase
iterator erase (iterator position);
iterator erase (iterator first, iterator last);
Get the first element reference front and the last element reference back
reference front():返回首元素的引用
reference back():返回尾元素的引用
resize(n, value) Modify size
Modify the container size, and use value to change the larger part to the default value.
for (int i=1;i<10;i++) myvector.push_back(i);
myvector.resize(5);
myvector.resize(8,100);
myvector.resize(12);
//myvector包含:1 2 3 4 5 100 100 100 0 0 0 0
array flip
Use reverse() in <algorthm>
#include <algorithm>
reverse(A.begin(),A.end())
copy vector
Copy during initialization and construction
vector<int> tem(list);
assign
vector<int> temlist;
temlist.assign(list.begin(), list.end());
Algorithm
unique
unique removes adjacent duplicate elements. If you want to remove all (including non-adjacent) elements, you must first sort the sequence so that all duplicate elements are adjacent.
unique returns, the next iterator of the last retained element
vector<int> myvector = {
1,2,2,2,3,3,2,2,1}
vector<int>::iterator it = unique(myvector.begin(),myvecotr.end())
#out:1,2,3,2,1,?,?,?,?
myvector.erase(it,myvector.end())
#out:1,2,3,2,1
sortsort
//升序
sort(A.begin(),A.end(),less<int>());
//降序
sort(A.begin(),A.end(),greater<int>());
Custom comparison function
[sort] is generated in the opposite order to [Heap/Priority Queue].
are all default less<>() comparison functions, but after [sort] the elements are arranged in ascending order ; [heap /priority queue] generateslarge top heap.
Note: Note that >= or <= must not be written in the comparison function. The comparison function requires that if two elements are equal, false should be returned. If the two elements here are equal, true is returned, causing the stl sort to be executed abnormally and causing a segfault.
Pass in comparison function
How to write anonymous functions
struct Edge {
int len, x, y;
Edge(int len, int x, int y) : len(len), x(x), y(y) {
}
};
sort(edges.begin(), edges.end(), [](Edge a, Edge b) -> int {
return a.len < b.len; });
Overloaded operators
The comparison result of priority_queue is [opposite]
class Point{
public:
int x;
int y;
int dist;
Point(int x,int y,int dist){
this->x = x;
this->y = y;
this->dist = dist;
}
//根据【希望】的情况进行返回
bool operator<(const Point &p) const{
return dist>p.dist;
}
};
priority_queue<Point> q;
max_element
vector<int> arr = {
1,2,3,4};
int maxNum = *max_element(arr.begin(),arr.end());
cout << maxNum << endl; // 4
Queue — queue
#include <queue>
queue<int> q;
Queue operations
Get the team leader
q.front(); //获得队列最前面一个元素引用
Get to the end of the queue
q.back(); //返回队列最后一个元素引用
Call it short
q.empty(); //检查是否为空的方法
Join the team
q.push(); //在队列尾添加一个数据
Dequeue
Return void
q.pop(); //删除队列头的一个数据,返回void
size()The number of elements in the queue
Stack —Stack
#include <stack>
stack<int> mystack;
Stack operations
short operation
s.empty(); //如果栈为空则返回true, 否则返回false;
Get size
s.size(); //返回栈中元素的个数
Get the top element of the stack
s.top(); //返回栈顶元素, 但不删除该元素
pop
s.pop(); //弹出栈顶元素, 但不返回其值
push into stack
s.push(); //将元素压入栈顶
s.emplace(); //构造并插入元素
heap
The heap is not a container, but a special way of organizing container elements.
Heap operations
create heap
vector<int> A = {
};
//构造 小顶堆
mack_heap(A.begin(),A.end(),greater<>());
//构建 大顶堆(默认)
mack_heap(A.begin(),A.end(),less<>());
insert into heap
A.push_back(x);
//greater/less必须与创建堆使用的相同
push_heap(A.begin(),A.end(),greater<>());
push_heap() will therefore think that the last element is a new element, and will rearrange the sequence in order to maintain the heap structure.
Delete the top of the heap
pop_heap(A.begin(),A.end());
A.pop_back();
pop_head moves the first element to the end
Check if it is a heap
is_heap(A.begin(),A.end());
Heap sort
//大顶堆
make_heap(A.begin(), A.end());//{12 10 3.5 6.5 8 2.5 1.5 6}
//升序排列
sort_heap(A.begin(), A.end());//{1.5 2.5 3.5 6 6.5 8 10 12}
//小顶堆
make_heap(A.begin(), A.end(),greater<>());// {1.5 6 2.5 6.5 8 12 3.5 10}
//降序排列
sort_heap(A.begin(), A.end(),greater<>());//{12 10 8 6.5 6 3.5 2.5 1.5}
priority queue
When comparing pairs, compare the first element first, and compare the second element if the first element is equal.
//pair<x,y>键值对
priority_queue<pair<int, int>> q;
//降序队列,大顶堆,默认
priority_queue <int,vector<int>,less<int> >q;
//升序队列,小顶堆
priority_queue <int,vector<int>,greater<int> > q;
insert
//构造插入
q.emplace(dist, i);
push();
delete
q.pop(); //无返回值
get top
q.top();
Custom comparison function
Example 1
Anonymous function + decltype inferred type + constructor
auto cmp = [](const pair<string, int>& a, const pair<string, int>& b) {
return a.second == b.second ? a.first < b.first : a.second > b.second;
};
priority_queue<pair<string, int>, vector<pair<string, int>>, decltype(cmp)> queue(cmp);
Example 2
Comparison function in the structure + passing in the comparison function generic
struct cmp {
bool operator ()(pair<string, int>& a, pair<string, int>& b) {
return a.second == b.second ? a.first < b.first : a.second > b.second;
}
};
priority_queue<pair<string, int>, vector<pair<string, int>>, cmp> queue;
Hash table
map ascending and descending order
map<int,int,less<int>> mmap; //默认升序
map<int,int,greater<int>> mmap; //降序
Hash table operations
#include <unordered_map>
unordered_map<string,int> map,
insert
map.insert (x); // 复制插入
map.insert (make_pair<string,double>("x",y)); // 移动插入
map.emplace(7, "456"); //构造插入
delete
map.erase(map.begin()+x); //通过位置
map.erase("x"); //通过key
Clear
map.clear();
Find
if(map.find("x") != map.end()){
//查找成功
}else{
//查找失败
}
if (map.count("x")) {
//查找成功
}
int val = map["x"];
//直接使用key值访问键值对,如果没有访问到,返回0
Traverse
map里面的数据类型是pair<T,P> p = {
key,value}
//first 是map的key
//second 是map的value
for (auto& [key,value]: map)
cout << key << " "<< value << endl;
for(auto it=map.begin();it!=map.end();it++){
}
gather
The difference between set and unordered_set in c++ std is similar to the difference between map and unordered_map:
set is implemented based on the red-black tree. The red-black tree has the function of automatic sorting, so all the data inside the map is in order at all times.
unordered_set Based on the hash table, the time complexity of data insertion and search is very low, almost constant time, but the cost is that it consumes a lot of memory and has no automatic sorting function. In the underlying implementation, an array with a relatively large subscript range is used to store elements, forming many buckets, and the hash function is used to map the keys to different areas for storage.
unordered_set<int,int> set;
insert
emplace
insert
push_back()
append()
delete
erase
pop_back()
Find
count
find
Traverse
for (auto& x: set)
cout << x << endl;
Custom set sorting
Modern C++20
auto cmp = [](int a, int b) {
return ... };
set<int, decltype(cmp)> sset;
Modern C++11
The lambda expression needs to be passed into the constructor.
auto cmp = [](int a, int b) {
return ... };
std::set<int, decltype(cmp)> sset(cmp);
Old solution uses struct's operator()
function followed by const
to indicate a constant function (const member function).
An explanation of C++’s constant Member function
const member function
Member variables (data members) cannot be modified within.const object
can only callconst member function
.
struct cmp {
bool operator() (int a, int b) const {
return ...
}
};
set<int, cmp> sset;
for loop
for-each
//for-each
for(auto c:S){
ascii[c]++;
}
Array assignment memset
memset(A,0,sizeof(A));
key-value pair
Create pair
//创建一个空的pair对象(使用默认构造),它的两个元素分别是T1和T2类型,采用值初始化。
pair<T1, T2> p1;
//创建一个pair对象,它的两个元素分别是T1和T2类型,其中first成员初始化为v1,second成员初始化为v2。
pair<T1, T2> p2(v1, v2);
Create new pair
// 以v1和v2的值创建一个新的pair对象,其元素类型分别是v1和v2的类型。
pair<T1, T2> p3 = make_pair(v1, v2);
or
pair<T1, T2> p3 = {
v1,v2};
Visit pair
// 返回对象p1中名为first的公有数据成员
p.first;
// 返回对象p1中名为second的公有数据成员
p.second;
example
//二维数组
vector<vector<int>> m;
queue<pair<int, int>> q;
q.push({
r0, c0 });
//m[i][0] = r0,m[i][1]= c0
//或者说 插入一个[r0,c0] , 或者说 插入一个 一维数组
//此时二维数组元素 [ [r0,c0] ]
m.push_back({
r0, c0 });
pair<int, int> cur = q.front();
//pair访问
int x1 = cur.first + x[j];
int y1 = cur.second + y[j];
tuple tuple
Use of tuple
vector<tuple<int, int, int, int>> ans;
ans.emplace_back(steps, grid[i][j], i, j);
Create a tuple
# 1.
tuple<int,flaot,vector<int>> t;
# 2.
tuple<string,vector<double>,int> someVal("tuple",{
2.14,3.15},100);
# 3.
tuple<int,int,double> someVal{
2,3,3.15};
access tuple
auto item = make_tuple("string",3,20.01);
auto book = get<1>(item);
Query the number of tuple members
auto sz = tuple_size<decltype(item)>::value;
//sz = 3
Query tuple member type
tuple_element<1,decltype(item)>::type ctype;
//ctype的类型为int
string string
There is no need to add '\0' at the end of string
string::npos 表示 字符串末尾
Basic operations
string s;
1) s.empty(); // s为空串 返回true
2) s.size();s.length(); // 返回s中字符个数 类型应为:string::size_type
3) s[n]; // 从0开始相当于下标访问
4) s1+s2; // 把s1和s2连接成新串 返回新串
5) s1=s2; // 把s1替换为s2的副本
6) v1==v2; // 比较,相等返回true
7) `!=, <, <=, >, >=` 惯有操作 任何一个大写字母都小于任意的小写字母
8) s.push_back() //其他操作类似于vector
Case conversion
string str = 'Abc';
//转大写
transform(str.begin(), str.end(), str.begin(), toupper);
>>> str = 'ABC'
//转小写
transform(strA.begin(), strA.end(), strA.begin(), tolower);
substr finds substring
pos:
Position of the first character to be copied as a substring.
If this is equal to the string length, the function returns an empty string.
If this is greater than the string length, it throws out_of_range.
Note: The first character is denoted by a value of 0 (not 1).
- What is returned is a copy of the original string.
- Start counting from 0
- If pos is exactly [equal to] the length of the string, an empty string is returned.
- If pos is [greater than] the string length, an out_of_rang exception is thrown.
len:
Number of characters to include in the substring (if the string is shorter, as many characters as possible are used).
A value of string::npos indicates all characters until the end of the string.
- If the length of len is [greater than] the length of the remaining substring, take all of them.
- string::npos means removing all remaining substrings.
size_t:
size_t is an unsigned integral type (the same as member type string::size_type).
- Unsigned integer.
string substr(size_t pos,size_t len) const
//第一个参数是index,第二个参数是子串长度
stinrg str = s.substr(index,len);
string => const char*
string str = "Hello World";
const char *ch1 = str.c_str();
const char *ch2 = str.data();
Character deletion erase
c++98
sequence (1) string& erase (size_t pos = 0, size_t len = npos);
character (2) iterator erase (iterator p);
range (3) iterator erase (iterator first, iterator last);
Character operations
//替换字符
String splitting
s为原字符串,tokens为分割后字符串(需要传入),delimiters为分割符
void split(const string& s, vector<string>& tokens, const string& delimiters = " "){
string::size_type lastPos = s.find_first_not_of(delimiters, 0);
string::size_type pos = s.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos) {
tokens.push_back(s.substr(lastPos, pos - lastPos));//use emplace_back after C++11
lastPos = s.find_first_not_of(delimiters, pos);
pos = s.find_first_of(delimiters, lastPos);
}
}
//示例:
string s = "a,b,c";
vector<string> tokens;
split(s,tokens,",");
for(auto &t:tokens){
cout << t << " ";
}
>>> a b c
stringstream word segmentation (single space)
C++ std::move principle implementation and usage summary
move()
Its only function is to force an lvalue into an rvalue reference, and then the value can be used through an rvalue reference , for move semantics.
vector<string> uncommonFromSentences(string s1, string s2) {
unordered_map<string, int> freq;
//分割空格
auto insert = [&](const string& str){
stringstream ss(str); // ss << s;
string buffer;
while(ss >> buffer){
++freq[move(buffer)];
}
}
insert(s1);
insert(s2);
...
}
Character search
//返回str在字符串中第一次出现的位置(从index开始查找),如果没找到则返回string::npos
//string
size_type find( const basic_string &str, size_type index=0 );
//c-string
size_type find( const char *str, size_type index=0 ); // 同上
//返回str在字符串中第一次出现的位置(从index开始查找,长度为length),如果没找到就返回string::npos
//buffer
size_type find( const char *str, size_type index, size_type length );
// 返回字符ch在字符串中第一次出现的位置(从index开始查找),如果没找到就返回string::npos
//character
size_type find( char ch, size_type index=0 );
String comparison compare
unsigned int val = a.compare(b);
//string (1)
int compare (const string& str) const;
//substrings (2)
int compare (size_t pos, size_t len, const string& str) const;
int compare (size_t pos, size_t len, const string& str,size_t subpos, size_t sublen) const;
//c-string (3)
int compare (const char* s) const;
int compare (size_t pos, size_t len, const char* s) const;
//buffer (4)
int compare (size_t pos, size_t len, const char* s, size_t n) const;
char* => int
const char *str1 = "3.14159";
int num1 = std::atoi(str1);
string => int, double, long, long long …
string s = "123";
int num1 = stoi(s);
double num2 = stod(s);
long num3 = stol(s);
long long num4 = stoll(s);
stod(string str,size_t idx)
str:
String type image.
idx:
Pointer of type size_t. If idx is not empty,
sets idx to the next character after [numeric string]. Therefore, idx should be passed as pointer type, or reference type.
example:
string orbits("365.24 29.53");
size_t sz; //unsigned int64
double earth = stod(orbits,&sz);
cout << sz << orbits[sz] << 1 << endl;
double moon = stod(orbits.substr(sz));
cout << "The moon completes " << (earth/moon) << " orbits per Earth year.\n";
out:
6 1
The moon completes 12.3684 orbits per Earth year.
int => string
int num = 123;
string str = to_string(num);
char=>string
char ch = 'a'
string a = *new string(1, ch);
character stream stringstream
#include <sstream>
stringstream stream;
string sint="1";
string sfloat="1.1";
string sdouble="1.2";
int dint;
float dfloat;
double ddouble;
//string to int
stream << sint;
stream >> dint;
//string to float
stream.clear(); //注意需要清空对象
stream << sfloat;
stream >> dfloat;
//string to double
stream.clear(); //注意需要清空对象
stream << sdouble;
stream >> ddouble;
Determine whether a string is a letter isalpha
isalpha(s)
Returns true for uppercase and lowercase letters, false for others.
anonymous function
C++11 provides support for anonymous functions, called Lambda functions (also called Lambda expressions). The specific form of Lambda expressions is as follows:
[capture](parameters )->return-type{body}
If has no parameters, the empty parentheses () can be omitted.
[capture]->return-type{body}
Ifthere is no return value, the return value can also be omitted,
[capture](parameters){body}
//例子
[](int x, int y) -> int {
int z = x + y; return z; }
A Lambda function canreference variables declared outside it. The collection of these variables is called a closure. The closure is defined in the Lambda Within square brackets [] in an expression declaration. This mechanism allows these variables to be captured by value or by reference. Examples of these are:
[] //未定义变量.试图在Lambda内使用任何外部变量都是错误的.
[x, &y] //x 按值捕获, y 按引用捕获.
[&] //用到的任何外部变量都隐式按引用捕获
[=] //用到的任何外部变量都隐式按值捕获
[&, x] //x显式地按值捕获. 其它变量按引用捕获
[=, &z] //z按引用捕获. 其它变量按值捕获
decltype keyword
Sometimes we want to infer the type of a variable to be defined from the type of an expression, but we don't want to initialize the variable with the value of the expression (if we want to initialize, use auto). In order to meet this demand, the new C++11 standard introduces the decltype type specifier. Its function is to select and return the data type of the operand. In this process, the compiler analyzes the expression and obtains its type, but does not Actually evaluates the expression.
int getSize();
int main(void)
{
int tempA = 2;
/*1.dclTempA为int*/
decltype(tempA) dclTempA;
/*2.dclTempB为int,对于getSize根本没有定义,但是程序依旧正常,因为decltype只做分析,并不调用getSize,*/
decltype(getSize()) dclTempB;
return 0;
}
Both decltype and auto can be used to infer types, but there are several obvious differences between them:
- auto ignores top-level const, decltype retains top-level const;
- For reference operations, auto infers the original type, and decltype infers the reference;
- For dereference operations, auto infers the original type and decltype infers the reference;
- Auto inference will actually be executed, decltype will not be executed, only analysis will be done.
In short, special care needs to be taken when combining const, references and pointers during use.