ACM模式记录 c++
一、读取输入
1. 理论
cin
在’空格’、‘Tab’、'回车’处截断
string a, b, c; cin >> a >> b >> c;
getline(cin, string)
读取一行,需要 #include
注意: 会读取最后的换行符
string input = ""; getline(cin, input); // 可以指定'#'或其他符号为结束字符,这时候敲击‘回车’键,输入不会终止 getline(cin, input, '#');
2. 实战
输入字符串,根据空格隔开
vector<string> vec_str; string str; while(cin>>str) vec_str.push_back(str);
输入带空格的字符串
string a; getline(cin,a)
输入字符串个数、一行字符串、空格隔开
输入有两行。第一行n;第二行是n个空格隔开的字符串
int n; cin >> n; vector<string> vec_str; string str; while (n--) { cin >> str; vec_str.push_back(str); str.clear(); }
输入字符串个数、N行字符串、每一行字符串由M个空格隔开
int n; int m; vector<vector<string>> vec_strs; cin >> n; cin >> m; while (n--) { vector<string> vec_str; while (m--) { string str; cin>>str; vec_str.push_back(str); } vec_strs.push_back(vec_str); }
输入字符串个数、N行字符串、每一行字符串代表一个字符串,包含空格的字符串
int n; vector<string> vec_strs; cin >> n; while (n--) { string vec_str; get_line(cin, vec_str); vec_strs.push_back(vec_str); }
在终端的一行中输入非固定数目的整型数字,并存到数组中,中间以空格(或者其他单字符,./)分隔
// 代码通过cin.get()从缓存中读取一个字节,这样就扩充了cin只能用空格和TAB两个作为分隔符。 // 发现是’\n’就知道一行结束了 vector<int> nums; int num; while (cin >> num) { nums.push_back(num); // if (getchar() == '\n') // 方法1:getchar if (cin.get() == '\n') // 方法2:cin.get break; }
在终端的一行中输入固定数目的整型数字,并存到数组中,中间以(其他单字符,./)分隔
3
1,2,3
int m; cin >> m; char sep; vector<int> nums(m); for (int i = 0; i < m - 1; ++i){ cin >> nums[i] >> sep; } cin >> nums[m - 1];
使用getline 读取一整行字符串到字符串input中,然后使用字符串流stringstream,读取单个数字或者字符。每个字符中间用’,'间隔
hello,world
hello world
#include <iostream> #include <string> #include <vector> #include <sstream> #include <algorithm> using namespace std; int main() { string input; while (getline(cin, input)) { //读取一行 vector<string> strs; string str; stringstream ss(input); while (getline(ss, str, ',')) { strs.push_back(str); } sort(strs.begin(), strs.end()); for (auto& str : strs) { cout << str << " "; } cout << endl; } return 0; }
给定一行字符串,每个字符串用空格间隔,一个样例为一行
1 2 3
6int main() { string input; while (getline(cin, input)) { //读取一行 stringstream data(input); //使用字符串流 int num = 0, sum = 0; while (data >> num) { sum += num; } cout << sum << endl; } return 0; }
输入矩阵
输入用逗号隔开的字符串,去除字符串填入数组
#include<string> #include<vector> #include<iostream> #include <algorithm> #include <sstream> using namespace std; int main() { int n; cin >> n; vector<vector<int>> vec(n, vector<int>(n)); for (int i = 0; i < n; ++i) {//注意这里一定要有i控制,用while容易一直输入导致错误 string s; cin >> s; replace(s.begin(), s.end(), ',', ' '); istringstream input(s); string tmp; for (int j = 0; j < n; ++j) {//内层循环也很重要 input >> tmp; vec[i][j] = stoi(tmp); } } return 0; }
字符串输入到数组
3
1,2,3,3,2
4,5,6,1,3
7,8,9,3,4
using namespace std; int main() { int n; cin >> n; vector<vector<int>> vec(n,vector<int>(5)); for (int i = 0; i < n;++i){//注意这里一定要有i控制,用while容易一直输入导致错误 string s; cin >> s; replace(s.begin(), s.end(), ',', ' '); istringstream input(s); string tmp; for (int j = 0; j < 5;++j){//内层循环也很重要 input >> tmp; vec[i][j] = stoi(tmp); } } for (int i = 0; i < vec.size(); i++) { for (int j = 0; j < vec[0].size(); j++) { cout << "输出是" << vec[i][j] << endl; } } return 0; }
输入链表
1 输入链表结点个数
2 输入链表的值struct ListNode { int m_nKey; ListNode* m_pNext; ListNode(int m) { m_nKey = m; m_pNext = nullptr; } }; int main() { int n; while(cin >> n) { vector<int> vec; ListNode* dummynode = new ListNode(0); ListNode* cur_node = dummynode; while(n--) { int cur; cin >> cur; ListNode* next_node = new ListNode(cur); cur_node->m_pNext = next_node; cur_node = cur_node->m_pNext; } } }
二、常用的STL模板及函数
1. vector(单端数组)
- vector和普通数组的区别
- 数组是静态的,长度不可改变,而vector可以动态扩展,增加长度
- 数组内数据通常存储在栈上,而vector中数据存储在堆上
头文件
#include <vector>
初始化
// 1.默认初始化;vector为空, size为0,表明容器中没有元素,而且 capacity 也返回 0,意味着还没有分配内存空间。这种初始化方式适用于元素个数未知,需要在程序中动态添加的情况。 vector<int> list1; // 2.拷贝初始化,此为浅拷贝;要求类型一致 vector<int> list2(list); vector<int> list2 = list; // 3.列表中元素的拷贝;其它类型会自动转换为int vector<int> list = {1,2,3,4,5,6,7}; vector<int> list {1,2,3,4,5,6,7}; vector<int> list3(list.begin(), list.end()); //比较常用,可指定启止位置 // 4.赋值初始化 vector<int> list4(7); // 会在list中压入7个0,默认值初始化 vector<int> list5(7,3); // 会在list中压入7个3,指定值初始化
用法
容量与大小
empty(); // 判断容器是否为空,为空返回1,否则返回0 capacity(); // 返回容器的容量 size(); // 返回容器的大小,即容器中元素的个数 resize(int num); // 重新指定容器的长度为num。若容器变长,则以默认值0填充新位置;如果容器变短,则末尾超过容器长度的元素被删除 resize(int num,int elem); // 重新指定容器的长度为num,若容器变长,则以elem填充新位置,如果容器变短,则末尾超过容器长度的元素被删除 // resize特性:长赋值,短截断
插入和删除
push_back(ele); // 尾部插入元素ele pop_back(); // 删除最后一个元素 insert(const_iterator pos,ele); // 在迭代器指向的位置pos处插入一个元素ele insert(const_iterator pos,int count,ele); // 在迭代器指向的位置pos处插入count个元素ele erase(const_iterator pos); // 删除迭代器指向的元素 erase(const_iterator begin,const_iterator end); // 删除迭代器从begin到end之间的元素 clear(); // 删除容器中所有元素
数据存取
at(int idx); // 返回索引idx所指的数据 operator[]; // 返回[]内索引所指的数据 front(); // 返回容器中第一个元素 back(); // 返回容器中最后一个元素
互换
v1.swap(v2); // 容器v2和容器v1互换 swap(v1[0], v1[2]) // 容器v1中第0个元素和第2个元素互换
2. string(字符串)
头文件
#include <string>
初始化
string s1; // 默认初始化,创建一个空的字符串 string s2(s1); // 拷贝初始化,浅拷贝 string s2 = s1; string str3("hello world"); // 使用字符串字面量初始化 string str3 = "hello world"; string str2(5, 'c'); // 使用5个字符c初始化 string str4(str3, 5, 4); // 将str3以5为索引开始,长度为4字串为初值
用法
插入和删除
string& insert(int pos,const char* s); // 插入字符串 string& insert(int pos,const string &str); // 插入字符串 string& insert(int pos,int n,char c); // 在指定位置插入n个字符c string& erase(int pos,int n = npos); // 删除从pos开始的n个字符
数据存取
char& operator[](int n); // 通过 [] 方式取字符 char& at(int n); // 通过at方法获取字符
查找和替换
int find(const string& str,int pos = 0)const; // 查找str第一次出现的位置,从pos开始查找 int find(const char* s,int pos = 0)const; // 查找s第一次出现位置,从pos开始查找 int find(const char *s,int pos,int n)const; // 从pos位置查找s的前n个字符第一次位置 int find(const char c,int pos = 0)const; // 查找字符c第一次出现位置 int rfind(const string& str, int pos = npos)const; // 查找str最后一次出现位置,从pos开始查找 int rfind(const char* s,int pos = npos)const; // 查找s最后一次出现位置,从pos开始查找 int rfind(const char* s,int pos,int n )const; // 从pos查找s的前n个字符最后一次位置 int rfind(const char c,int pos = 0)const; // 查找字符c最后一次出现位置 string& replace(int pos,int n,const string& str); // 替换从pos开始的n个字符为字符串str string& replace(int pos,int n,const char* s); // 替换从pos开始的n个字符为字符串s
拼接
string& operator+=(const string& str); // 重载+=运算符 string& operator+=(const char* str); // 重载+=运算符 string& operator+=(const char c); // 重载+=运算符 string& append(const char *s); // 把字符串s连接到当前字符串结尾 string& append(const char *s,int n); // 把字符串s的前n个字符连接到当前字符串结尾 string& append(const string &s); // 同operator+=() string& append(const string &s,int pos,int n); // 把字符串s中从pos开始的n个字符连接到当前字符串结尾 string& append( int n,char c); // 在当前字符串结尾添加n个字符c
比较
int compare(const string &s)const; // 与字符串s比较 int compare(const char*s)const; // 与字符串s比较 // compare函数在>时返回1,<时返回-1,相等时返回0,比较区分大小写,逐个字符比较
子串
string substr(int pos = 0,int n = npos)const; // 返回由pos开始的n个字符组成的字符串
3. deque(双端队列)
头文件
#include <deque>
初始化
string s1; // 默认初始化,创建一个空的字符串 string s2(s1); // 拷贝初始化,浅拷贝 string s2 = s1; string str3("hello world"); // 使用字符串字面量初始化 string str3 = "hello world"; string str2(5, 'c'); // 使用5个字符c初始化 string str4(str3, 5, 4); // 将str3以5为索引开始,长度为4字串为初值
用法
容量与大小
empty(); // 判断容器是否为空,为空返回1,否则返回0 size(); // 返回容器的大小,即容器中元素的个数 resize(int num); // 重新指定容器的长度为num。若容器变长,则以默认值0填充新位置;如果容器变短,则末尾超过容器长度的元素被删除 resize(int num,int elem); // 重新指定容器的长度为num,若容器变长,则以elem填充新位置,如果容器变短,则末尾超过容器长度的元素被删除 // resize特性:长赋值,短截断
插入和删除
push_back(elem); // 在容器尾部添加一个数据 push_front(elem); // 在容器头部插入一个数据 pop_back(); // 删除容器最后一个数据 pop_front(); // 删除容器第一个数据 insert(int pos,elem); // 在pos位置插入元素elem clear(); // 移除容器的所有数据 erase(begin,end); // 删除[begin,end)区间的所有元素 erase(int pos); // 删除pos位置的数据
数据存取
at(int idx); // 返回索引idx所指的数据,如果idx越界,抛出out_of_range异常 operator[]; // 返回索引idx所指的数据,越界时,运行直接报错 front(); // 返回容器中第一个数据元素 back(); // 返回容器中最后一个数据元素
4. queue(队列)
头文件
#include <queue>
初始化
string s1; // 默认初始化,创建一个空的字符串 string s2(s1); // 拷贝初始化,浅拷贝 string s2 = s1; string str3("hello world"); // 使用字符串字面量初始化 string str3 = "hello world"; string str2(5, 'c'); // 使用5个字符c初始化 string str4(str3, 5, 4); // 将str3以5为索引开始,长度为4字串为初值
用法
容量与大小
empty(); // 判断容器是否为空,为空返回1,否则返回0 size(); // 返回容器的大小,即容器中元素的个数
插入和删除
push(elem); // 往队尾添加元素 pop(); // 从队头移除第一个元素 back(); // 返回最后一个元素 front(); // 返回第一个元素
5. stack(栈)
头文件
#include <stack>
初始化
string s1; // 默认初始化,创建一个空的字符串 string s2(s1); // 拷贝初始化,浅拷贝 string s2 = s1; string str3("hello world"); // 使用字符串字面量初始化 string str3 = "hello world"; string str2(5, 'c'); // 使用5个字符c初始化 string str4(str3, 5, 4); // 将str3以5为索引开始,长度为4字串为初值
用法
数据存取
push(elem); // 向栈顶添加元素 pop(); // 从栈顶移除第一个元素 top(); // 返回栈顶元素
6. list(列表)
头文件
#include <queue>
初始化
string s1; // 默认初始化,创建一个空的字符串 string s2(s1); // 拷贝初始化,浅拷贝 string s2 = s1; string str3("hello world"); // 使用字符串字面量初始化 string str3 = "hello world"; string str2(5, 'c'); // 使用5个字符c初始化 string str4(str3, 5, 4); // 将str3以5为索引开始,长度为4字串为初值
用法
容量与大小
empty(); // 判断容器是否为空,为空返回1,否则返回0 size(); // 返回容器的大小,即容器中元素的个数 resize(int num ,elem); // 重新指定容器长度为num,若容器变长,则以elem值填充新位置,未指定elem值则以默认值0填充,若容器变短,则末尾超出容器长度的元素被删除
插入和删除
push_back(elem); // 在容器尾部加入一个元素 pop_back(); // 删除容器中最后一个元素 push_front(elem); // 在容器开头插入一个元素 pop_front(); // 在容器开头移除一个元素 insert(pos,elem); // 在pos位置插入elem元素的拷贝,返回新数据的位置 insert(pos,n,elem); // 在pos位置插入n个elem元素,无返回值 insert(pos,begin,end); // 在pos位置插入[begin,end)区间的数据,无返回值 clear(); // 移除容器的所有数据 erase(begin,end); // 删除[begin,end)区间的数据,返回值下一个数据的位置 erase(pos); // 删除pos位置的数据,返回下一个数据的位置 remove(elem); // 删除容器中所有与elem匹配的元素
数据存取
front(); // 返回第一个元素 back(); // 返回最后一个元素
2. set(集合)
基础
- 所有元素都会在插入时自动排序
- 底层结构是用二叉树实现
- 不允许容器中有重复的元素;multiset允许容器中有重复的元素
头文件
#include <set>
初始化
// 1.默认初始化 Set<int> s1; // 2.拷贝初始化,此为浅拷贝;要求类型一致 Set<int> s2(s1); Set<int> s2 = s1; // 3..列表中元素传值初始化 set<string> st{"good", "bad", "medium"};
用法
Set的容量与大小
empty(); // 判断容器是否为空,为空返回1,否则返回0 size(); // 返回容器的大小,即容器中元素的个数
Set的插入和删除
insert(elem); // 在容器中插入一个元素elem erase(const_iterator pos); // 删除迭代器指向的元素 erase(const_iterator begin,const_iterator end); // 删除迭代器[begin, end)的元素 erase(elem) // 删除容器中值为elem的元素 clear(); // 删除容器中所有元素
Set的查找和统计
find(elem); // 查找elem是否存在,若存在则返回该元素的迭代器;若不存在,则返回set.end(); count(elem); // 统计elem元素的个数 由于set容器中不允许含有重复元素,则值会返回0或者1;
Set互换