C++ STL数据结构学习笔记:vector/string容器
·
导读:本文是C++数据结构学习系列的第一篇,主要讲解STL中最常用的两个容器——
vector动态数组和string字符串容器。这些内容是C++编程的基础,也是算法竞赛和面试中高频考察的知识点。
目录
一、vector容器
vector是C++ STL中最常用的容器之一,它是一个动态数组,可以自动扩展容量。与普通数组相比,vector不需要预先指定大小,可以动态地添加和删除元素。
1.1 vector的创建方法
#include<bits/stdc++.h>
using namespace std;
int main() {
// 1. 创建空数组
vector<int> vec;
vec.push_back(1); // 空数组只能通过push_back添加元素
vec.push_back(2);
// 2. 创建数组指定元素个数(默认初始化为0)
int n = 10;
vector<int> vec1(n); // 10个元素,默认值为0
vector<int> vec2(n, -1); // 10个元素,全部初始化为-1
// 3. 拷贝构造——使用已存在的数组创建新数组
vector<int> vec3(vec2); // 拷贝vec2的所有元素
// 4. 使用已存在数组的一部分创建新数组
vector<int> vec4(vec1.begin() + 4, vec1.end()); // 从索引4到末尾
// 5. 列表初始化
vector<int> vec5 = {1, 2, 3, 4, 5, 6};
return 0;
}
创建方式汇总表:
| 创建方式 | 代码示例 | 说明 |
|---|---|---|
| 空数组 | vector<int> vec; |
需要push_back添加元素 |
| 指定大小 | vector<int> vec(n); |
默认初始化为0 |
| 指定大小和值 | vector<int> vec(n, val); |
所有元素初始化为val |
| 拷贝构造 | vector<int> vec2(vec1); |
复制vec1的所有元素 |
| 区间构造 | vector<int> vec(vec1.begin(), vec1.end()); |
复制指定区间 |
| 列表初始化 | vector<int> vec = {1,2,3}; |
C++ 11特性 |
1.2 vector与输入
定长输入:
#include<iostream>
#include<vector>
using namespace std;
int main() {
int n;
cin >> n;
vector<int> vec;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
vec.push_back(x);
}
// 或者使用指定大小的vector直接通过下标输入
vector<int> vec1(n);
for (int i = 0; i < n; i++) {
cin >> vec1[i];
}
return 0;
}
不定长输入:
// 结束输入方法:输入非数字字符或Ctrl+Z(添加EOF结束符)
vector<int> vec;
int x;
while (cin >> x) {
vec.push_back(x);
}
1.3 vector常用函数
| 函数名 | 作用 |
|---|---|
size() |
返回元素数量 |
empty() |
判断是否为空 |
push_back() |
在末尾添加元素 |
pop_back() |
移除最后一个元素 |
front() |
返回第一个元素 |
back() |
返回最后一个元素 |
begin() / end() |
返回首/尾迭代器 |
clear() |
清空所有元素 |
insert() |
在指定位置插入元素 |
erase() |
删除指定元素 |
resize() |
改变元素数量 |
reserve() |
预分配容量 |
capacity() |
返回当前容量 |
swap() |
交换两个vector |
vector<int> vec(10, 0);
vec.push_back(1); // 末尾插入元素1
vec.pop_back(); // 删除末尾元素(空数组不能pop_back)
vec.capacity(); // 返回当前容量
vec.resize(5); // 保留前5个元素,容量不变
vec.reserve(20); // 预分配容量为20(容量无法改小)
1.4 vector的迭代器
迭代器是指向容器中元素的"指针",可以用来遍历容器。
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<int> vec = {1, 2, 3, 4, 5, 6};
vector<int>::iterator begin_i = vec.begin();
vector<int>::iterator end_i = vec.end();
// 通过迭代器遍历
for (vector<int>::iterator i = begin_i; i < end_i; i++) {
cout << *i << " "; // 解引用获取元素值
}
return 0;
}
1.5 vector的增强for循环
C++11引入的范围for循环,写法更简洁:
vector<int> vec = {1, 2, 3, 4, 5, 6};
// 增强for循环(auto自动推导类型)
for (auto i : vec) {
cout << i << " ";
}
1.6 vector的sort排序
sort()函数在<algorithm>头文件中,默认升序排序。自定义排序有三种方式:
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
// 方式1:比较函数
bool cmp(int a, int b) {
return a > b; // 从大到小
}
// 方式2:函数对象(仿函数)
class cmp1 {
public:
bool operator()(int a, int b) {
return a > b; // 从大到小
}
};
int main() {
vector<int> vec = {2, 1, 4, 3, 6, 5, 7, 8, 9};
// sort(vec.begin(), vec.end(), cmp); // 方式1
// sort(vec.begin(), vec.end(), cmp1()); // 方式2
// 方式3:lambda表达式(推荐)
sort(vec.begin(), vec.end(), [=](int a, int b) {
return a > b; // 从大到小
});
/*
lambda格式:[] () {}
[]: 捕获外部变量
[=]: 值捕获(只读)
[&]: 引用捕获(可读写)
(): 参数列表
{}: 函数体
*/
for (auto i : vec) {
cout << i << " ";
}
return 0;
}
LeetCode实战:977. 有序数组的平方
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for (int i = 0; i < nums.size(); i++) {
nums[i] *= nums[i]; // 先求平方
}
sort(nums.begin(), nums.end()); // 再排序
return nums;
}
};
1.7 vector创建二维数组
#include<iostream>
#include<vector>
using namespace std;
int main() {
int n = 10;
// 创建空二维数组
vector<vector<int>> vec1;
// 创建n*n的二维数组,初始化为1
vector<vector<int>> vec2(n, vector<int>(n, 1));
cout << vec2[0][1] << endl; // 访问元素
// 遍历输出
for (int i = 0; i < vec2.size(); i++) {
for (int j = 0; j < vec2[i].size(); j++) {
cout << vec2[i][j] << " ";
}
cout << endl;
}
// 增强for循环遍历
for (auto i : vec2) {
for (auto j : i) {
cout << j << " ";
}
cout << endl;
}
return 0;
}
LeetCode实战:59. 螺旋矩阵 II
class Solution {
public:
vector<vector<int>> vec;
vector<vector<int>> generateMatrix(int n) {
vec.resize(n, vector<int>(n));
int t = 0, b = n - 1; // 上下边界
int l = 0, r = n - 1; // 左右边界
for (int num = 1; num <= n * n; ) {
for (int i = l; i <= r; i++) vec[t][i] = num++; // 从左到右
t++;
for (int i = t; i <= b; i++) vec[i][r] = num++; // 从上到下
r--;
for (int i = r; i >= l; i--) vec[b][i] = num++; // 从右到左
b--;
for (int i = b; i >= t; i--) vec[i][l] = num++; // 从下到上
l++;
}
return vec;
}
};
二、string字符串容器
string是C++ STL中的字符串容器,封装了C语言中的字符数组,提供了丰富的字符串操作方法。
2.1 cin输入
cin读取字符串时,遇到空格、制表符、回车即停止。
#include<bits/stdc++.h>
using namespace std;
int main() {
vector<string> vec;
string s;
// 定长输入
int n; cin >> n;
for (int i = 0; i < n; i++) {
cin >> s;
vec.push_back(s);
}
// 不定长输入
while (cin >> s) {
vec.push_back(s);
}
for (auto i : vec) {
cout << i << endl;
}
return 0;
}
2.2 getline输入
getline可以读取整行字符串,包括空格。
#include<bits/stdc++.h>
using namespace std;
int main() {
vector<string> vec;
string s;
// 读取一行(包括空格)
getline(cin, s);
cout << s << endl;
// 不定行数输入
while (getline(cin, s)) {
vec.push_back(s);
}
for (auto i : vec) {
cout << i << endl;
}
return 0;
}
2.3 cin与getline混合输入
当先使用cin再使用getline时,必须在cin之后使用cin.ignore()清除缓冲区中的换行符。
#include<bits/stdc++.h>
using namespace std;
int main() {
vector<string> vec;
string s;
int n; cin >> n;
// 关键:清除cin留下的换行符
cin.ignore();
for (int i = 0; i < n; i++) {
getline(cin, s);
vec.push_back(s);
}
for (auto i : vec) {
cout << i << endl;
}
return 0;
}
2.4 string常用处理函数
| 函数 | 作用 | 示例 |
|---|---|---|
push_back(c) |
尾部插入字符 | s.push_back('a'); |
insert(pos, str) |
指定位置插入 | s.insert(2, "abc"); |
erase(pos, len) |
删除指定位置字符 | s.erase(4, 2); |
find(str) |
查找子串位置 | s.find("cd"); |
substr(pos, len) |
截取子串 | s.substr(4, 4); |
pop_back() |
删除末尾字符 | s.pop_back(); |
clear() |
清空字符串 | s.clear(); |
isdigit(c) |
判断是否为数字 | isdigit(s[0]); |
isalpha(c) |
判断是否为字母 | isalpha(s[0]); |
字符串查找与截取示例:
string s = "abcd1234abcd!@#";
// find()查找
cout << s.find('d') << endl; // 输出3
cout << s.find("cd") << endl; // 输出3
cout << s.find('y') << endl; // 未找到,返回一个很大的数
// 判断查找结果
size_t pos;
if ((pos = s.find('!')) != string::npos) {
cout << "找到了,位置:" << pos << endl;
}
// substr()截取
string s1 = s.substr(4); // 从下标4截取到最后
string s2 = s.substr(4, 4); // 从下标4截取4个字符 -> "1234"
// erase()删除
s.erase(4); // 从下标4删除到最后
s.erase(4, 15); // 从下标4删除15个字符
LeetCode实战:151. 反转字符串中的单词
class Solution {
public:
// 去除多余空格
void remove(string &s) {
int index = 0;
for (int i = 0; i < s.size(); ) {
if (s[i] == ' ') i++;
else {
if (index != 0) s[index++] = ' ';
while (i < s.size() && s[i] != ' ') {
s[index++] = s[i++];
}
}
}
s.erase(index);
}
string reverseWords(string s) {
remove(s);
reverse(s.begin(), s.end()); // 先整体翻转
int start = 0;
for (int i = 0; i < s.size(); i++) {
if (s[i] == ' ') {
reverse(s.begin() + start, s.begin() + i); // 再翻转每个单词
start = i + 1;
}
}
reverse(s.begin() + start, s.end()); // 翻转最后一个单词
return s;
}
};
更多推荐
所有评论(0)