C++学习
1164
2023.07.05
2025.12.07
发布于 未知归属地

C++ 数组
数组大小固定,里面的值可以更改
定义并初始化数组
double balance[10];
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
balance[4] = 50.0;
double balance[6] = {1000.0, 2.0, 3.4, 7.0, 50.0}; // 最后一位被赋了默认值0

STL容器
String:
构造函数:
string str1; // 创建一个空字符串对象
string str2 = "Hello"; // 使用C字符串初始化一个字符串对象
string str3(str2); // 使用另一个字符串对象初始化一个新的字符串对象
赋值操作:
string str1 = "Hello"; string str2 = str1; // 将一个字符串对象的值赋给另一个字符串对象
string str3 = "world"; str1 = str3; // 将一个字符串对象的值赋给另一个字符串对象
连接操作:
string str1 = "Hello"; string str2 = "world"; string str3 = str1 + " " + str2; // 将两个字符串对象连接在一起
string str1 = "Hello"; string str2 = "world"; str1.append(" "); // 将一个字符串对象连接到另一个字符串对象的末尾 str1.append(str2);
比较操作:
string str1 = "Hello"; string str2 = "Hello"; if (str1 == str2) { // 判断两个字符串对象是否相等 cout << "str1 and str2 are equal." << endl; }
string str1 = "Hello"; string str2 = "World"; if (str1 < str2) { // 判断一个字符串对象是否小于另一个字符串对象 cout << "str1 is less than str2." << endl; }
子串操作:
string str1 = "Hello world"; string str2 = str1.substr(6, 5); // 从一个字符串对象中提取一个子串 cout << "str2 is: " << str2 << endl;
string str1 = "Hello world"; str1.erase(5, 6); // 删除一个字符串对象的子串 cout << "str1 is now: " << str1 << endl;
查找操作:
string str1 = "Hello world"; size_t pos = str1.find("world"); // 在一个字符串对象中查找特定的子串 if (pos != string::npos) { cout << "The substring 'world' was found at position " << pos << endl; }
string str1 = "Hello world"; size_t pos = str1.rfind("l"); // 在一个字符串对象中从后往前查找特定的子串 if (pos != string::npos) { cout << "The last occurrence of 'l' was found at position " << pos << endl; }
其他操作:
string str1 = "Hello world"; int len = str1.size(); // 返回字符串对象中字符的数量 if (str1.empty()) { // 检查字符串对象是否为空 cout << "str1 is empty." << endl; }
string str1 = "Hello world"; const char* cstr = str1.c_str(); // 返回一个指向字符串对象所表示的C字符串的指针
求string的长度用
int len = str.size(); // 使用 size() 方法获取字符串长度
int len2 = str.length(); // 使用 length() 方法获取字符串长度

char
char就是ascii码,可直接比较(>, <, ==)
islower(char c) 是否为小写字母
isupper(char c) 是否为大写字母
isdigit(char c) 是否为数字
isalpha(char c) 是否为字母
isalnum(char c) 是否为字母或者数字
toupper(char c) 字母小转大
tolower(char c) 字母大转小

array
#include
using namespace std;

// 定义并初始化std::array
array<int, 5> arr = {1, 2, 3, 4, 5};

// 循环遍历赋值
array<int, 5> arr1;
for (int i = 0; i < 5; ++i) {
arr1[i] = i + 1;
}

// fill函数赋值
array<int, 5> arr2;
fill(arr2.begin(), arr2.end(), 0);

vector
C++标准库提供了vector容器类,它是一种动态数组,支持在数组末尾快速添加和删除元素,可以方便地实现数组的动态管理。vector的初始化和赋值有以下几种方法:
1、使用默认构造函数初始化
vector vec; // 初始化一个空的vector

2、使用构造函数初始化
可以使用vector的构造函数,将一个已有的数组或其他容器中的元素赋值给vector,例如:
int arr[] = {1, 2, 3, 4, 5}; v{ector vec(arr, arr + 5); // 将数组中的元素赋值给vector

3、使用初始化列表初始化
可以使用花括号{},使用初始化列表初始化vector,例如:
vector vec = {1, 2, 3, 4, 5}; // 直接在花括号中添加元素

4、使用assign函数赋值
可以使用assign函数,将另一个vector、数组或初始化列表中的元素赋值给vector,例如:
vector vec; vec.assign({1, 2, 3, 4, 5}); // 将初始化列表中的元素赋值给vector
使用push_back函数添加元素

5、可以使用push_back函数,逐个添加元素到vector中,例如:
vector vec; vec.push_back(1); vec.push_back(2); vec.push_back(3);

vector.insert(pos, value); // 在 pos 处插入单个元素 value
vector.insert(pos, n, value); // 在 pos 处插入 n 个元素,每个元素的值为 value
vector.insert(pos, first, last); // 在 pos 处插入区间 [first, last) 中的元素
std::sort(vec.begin(), vec.end());

切片:
image.png

构造二维vector
初始化默认为0
image.png

初始化默认为1

image.png

Vector初始化

image.png

Stack:
初始化:
Stack只接受一个参数

image.png

Stack.pop() 无返回值
Stack.pop()一次添加一个,stack.emplace()一次添加多个
列表初始化,单个元素可以()和{}
多个元素必须{}

image.png

Map:
初始化

image.png

查找字典的值可以用find,可以用[]

确定某个键是否在字典内,可用map.count()

遍历map的key,value:
std::map<int, int> m;
std::vector keys;
std::vector values;
for (auto kv : m) {
keys.push_back (kv.first); // 将键存入 keys
values.push_back (kv.second); // 将值存入 values
}

有序字典:

image.png

image.png

Pair

image.png

std::make_pair(x, y);
std::pair<int, int> p1 = std::make_pair(1, 2); // 显式指定类型
auto p2 = std::make_pair(3, 4); // 使用 auto 推断类型

Queue:

priority_queue

Deque

Set:

image.png

一些注意点:
在用指针的时候,最好用new

不能用 a<i< b, 应该用 a<i && i<b

Reverse(s.begin(), s.end())

列表初始化,单个元素可以()和{}
多个元素必须{}

Lambda
auto plus = [] (int a, int b) -> int { return a + b; }
int c = plus(1, 2);

取整的方法:
floor():向下取整
ceil():向上取整
round():四舍五入
trunc():整数部分

Sort函数

image.png

是用lambda函数

image.png

无限大和无限小

image.png

image.png

C++,可以用int表示任意进制数
Int a = 0x16; // 十六进制
Int b = 0b1; //二进制
Int c = 077; //八进制

to_string(a)
接受一个数,转成字符串,只能转成10进制字符串

stoi(const string &str, size_t *idx = 0, int base = 10) -> int

字符串转为int,
参数分别为字符串,字符串中要转换的子串的起始位置 和 字符串的进制。

转为字符串的奇葩方法:

此时输出s为2a

转为二进制字符串:

求一个数的二进制位数:
int m = 32 - __builtin_clz(num);
int用__builtin_clz, long用64 - __builtin_clzl,long long用64 - __builtin_clzll

sstream 也是很好的str转int的方法

set里不可以放pair<int, int> ,可以 用a * base + b 把二维转一维
vector<vector> a, vector<pair<int, int>>a, vector<tuple<int, int, int>> a
可以直接a.push_back({a, b, c});

函数内定义函数可以 auto dfs = [&](int i, int cnt, bool is_limit) -> long long {}; 用lambda表达式
但是如果这个函数会递归调用,则不能用auto。
应该用function<long long(int, int, bool)> dfs = [&](int i, int cnt, bool is_limit) -> long long {};

求一个vector中最大的元素,
用*max_element(dp.begin(), dp.end())
max_element和min_element返回的是一个迭代器。

max有两种用法:
1、放两个数,如max(a, b)
2、放initializer_list, 如max({1, 2, 3, 4})

vector.begin(): 返回一个指向容器第一个元素的迭代器。
vector.end(): 返回一个指向容器末尾(最后一个元素的后一个位置)的迭代器。

memset(dp, 0, sizeof(dp)); 把数组dp全赋值0,也可以赋值二维dp
memset(dp, 0x3F, sizeof(dp)); 赋值无限大,0X7F为无限大,但这里用0x3F,这样两个无限大相加不会溢出
memset(dp, 0x80, sizeof(dp)); 赋值无限小
memset是按照字节赋值,但int占4个字节,只有赋值0和-1的时候是准确的

std::lower_bound: 返回一个迭代器,指向第一个不小于目标值的元素位置。如果第一个元素都大于目标的话,则返回vector.begin()。 如果最后一个元素都小于的话,则返回vector.end()。
std::upper_bound: 返回一个迭代器,指向第一个大于目标值的元素位置。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numbers = {1, 2, 2, 4, 4, 6, 8, 10};

    // 使用 std::lower_bound 查找第一个不小于目标值的元素位置
    auto lowerIt = std::lower_bound(numbers.begin(), numbers.end(), 4);

    // 使用 std::upper_bound 查找第一个大于目标值的元素位置
    auto upperIt = std::upper_bound(numbers.begin(), numbers.end(), 4);

    // 输出结果
    std::cout << "lower_bound: " << *lowerIt << " at index " << std::distance(numbers.begin(), lowerIt) << std::endl;
    std::cout << "upper_bound: " << *upperIt << " at index " << std::distance(numbers.begin(), upperIt) << std::endl;

    return 0;
}

std::equal_range 函数结合了 std::lower_bound 和 std::upper_bound 的功能,返回一个范围,表示有序序列中等于目标值的元素的区间。
这个函数返回一个 std::pair 对象,其中 first 成员是一个指向第一个等于目标值的元素的迭代器,second 成员是一个指向最后一个等于目标值的元素的迭代器。 若目标不存在则返回空
std::binary_search 是 C++ 标准库中的一个算法,用于在有序序列中判断是否存在目标值。
这个函数返回一个 bool 值,如果在指定的有序序列 [first, last) 中找到了等于 value 的元素,则返回 true;否则返回 false。

求一个vector的和, accumulate(arr.begin(), arr.end(), 0);

容器的复制:
arr2.resize(arr1.size());
copy_n(arr1.begin(), arr1.size(), arr2.begin()); \\ 从arr1中复制5个元素到arr2中
copy_n对于vector不会动态拓展大小,要确保arr2的大小大于arr1。

在做题时, 有时要用到visited,
unordered_set<pair<int, int>> visited; // 不对,因为没哈希函数
bool visited[m][n] // 可以

C++ 非结构化绑定支持pair和tuple, C++17支持vector和数组(未验证)
Python支持元祖,列表,字符串, 用*对剩余元素解包(放到列表里)。

建议对所有的变量在其定义的时候就对其进行初始化,这样可以避免许多无意的错误

C++ lambda函数的递归

岛屿数量

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int row = grid.size(), col = grid[0].size();
        int directions[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};

        auto dfs = [&](int i, int j, auto&& dfs_ref) -> void{
            grid[i][j] = '2';
            for (auto [dx, dy] : directions) {
                int nx = i + dx, ny = j + dy;
                if (nx < 0 || nx >= row || ny < 0 || ny >= col) continue;
                if (grid[nx][ny] == '1') dfs_ref(nx, ny, dfs_ref);
            }
        };

        int ans = 0;
        for (auto i = 0; i < row; ++i) {
            for (auto j = 0; j < col; ++j) {
                if (grid[i][j] == '1') {
                    ans++;
                    dfs(i, j, dfs);
                }
            }
        }
        return ans;
        
    }
};

visited集合要存pair<int, int>: vis.emplace(1LL*(u+k) << 32 | (l+k));
题目3694

124.二叉树中的最大路径和

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    // helper 函数返回左边的最大值和右边的最大值

    int maxPathSum(TreeNode* root) {
        int res = INT_MIN;
        function<int(TreeNode*)> helper = [&](TreeNode* node)-> int {
            if (node == nullptr) return 0;
            int left = max(0, helper(node->left));
            int right = max(0, helper(node->right));
            res = max(res, node->val + left + right);
            return node->val + max(left, right);
        };

        helper(root);
        return res;
        
        
    }
};

C++求次方,开方用math.h库中的pow函数,如平方pow(x, 2)

评论 (2)