入入入门
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
cin>> n;
cout<<**;
}
指针
源自:最详细的讲解C++中指针的使用方法(通俗易懂)_c++指针-优快云博客
入门:
指针就是内存地址,指针变量就是用来存放内存地址编码(计算机将内存换分为一个一个的字节,然后为每一个字节分配唯一的编码)的变量,不同类型的指针变量所占用的存储单元长度是相同的。
int* p = &a;
指针的const限定
写法:const 指向类型 *指针变量/ 指向类型 const *指针变量(const 在*前面)【表示不能通过指针修改被指向变量的值】
1.不能把一个const变量的地址 赋给一个 非const对象的指针
const double pi = 3.14;
double* ptr = π//错误,ptr是非const所指向的变量
const double* cptr = π//正确,cptr是const指针变量
2.允许把非const对象的地址 赋给指向const对象的指针,不能使用指向const对象的指针修改指向对象,然而如果该指针指向的是一个非const对象,可以用其他方法修改其所指向的对象
const double pi = 3.14;
const double* cptrf = π//正确
double f = 3.14;//f是double类型(非const类型)
cptr = &f;//正确,允许将f的地址赋给cptrf
f = 1.68;//正确,允许修改f的值
*cptrf = 10.3;//错误不能通过引用cptr修改f的值
3.实际编程过程中,指向const的指针常用作函数的形参,以此确保传递给函数的参数对象在函数中不能被修改
void fun(const int* p)
{
...
}
int main()
{
int a;
fun(&a);
}
指针作为函数的形参,在主函数中,我们定义整形变量a然后将a的地址传递给了子函数,对于子函数来说,
他的形参就是用const修饰过 的整型变量p指向主函数里a这个变量
这样的一系列操作就使得我们不能在子函数中通过p间接引用a 来改变a 的值,因为a 是用const修饰过的作就使得我们不能在子函数中通过p间接引用a 来改变a 的值,因为a 是用const修饰过的
summary:非const指针限定的指针不能指向const变量;const指针限定的指针不能使用*p修改被指向的值
const指针
指针类型* const 指针变量, ...;【const在*后】
int a = 10, b = 20;
int* const pc = &a;//pc是const指针
pc = &b;//错误pc 是只读的
pc = pc;//错误pc是只读的
pc++;//错误pc是只读的
*pc = 100;//正确,a被修改
字符串
C++中的String的常用函数用法总结_string函数-优快云博客
//cin string a;读入
cin>>a;
scanf("%s",a+1);//读入:asdffg【没有空格的字符串】
//一个string赋给另一个string
string a = str;[【sort返回的是void,不能string a =sort()】
//插入
s1.push_back('a');
//insert(pos,char):在指定的位置pos前插入字符
s1.insert(s1.begin(),'1');
//查找【找到后返回首字母在字符串中的下标】
cout << s.find("chicken") << endl; // 结果是:9
//string的排序
string s = "cdefba";
sort(s.begin(),s.end());
//string的分割/截取字符串
string s1("0123456789");
string s2 = s1.substr(2,5); // 结果:23456-----参数2:从s1[2]开始截取,参数5表示:截取多长
//访问元素
s[i]
结构体指针
C++死磕基础之指针篇(四)--结构体指针的定义以及使用_结构体指针如何定义和使用-优快云博客
vector
一维数组
详见:C++ vector 容器 | 菜鸟教程 (runoob.com)
//初始化
std::vector<int> myVector(5); // 创建一个包含 5 个整数的 vector,每个值都为默认值(0)
std::vector<int> myVector(5, 10); // 创建一个包含 5 个整数的 vector,每个值都为 10std::vector<int> a = original; // 调用赋值运算符
//增加元素
myVector.push_back(7); // 将整数 7 添加到 vector 的末尾
//size
int size = myVector.size(); // 获取 vector 中的元素数量
//迭代
for (auto it = myVector.begin(); it != myVector.end(); ++it) {/end指的是最后一个的下一个
std::cout << *it << " ";
}for (int element : myVector) {
std::cout << element << " ";
}for(int i = 0;i<myVector.size();i++){}
//清除
myVector.erase(myVector.begin() + 2); // 删除第三个元素
//排序
sort(vec.begin(), vec.end()); // 排序时通过迭代器访问元素
//翻转
reverse(s.begin(),s.end())
二维数组:
【C++】详解vector二维数组的全部操作(超细图例解析!!!)_二维vector-优快云博客
关于C++中二维vector使用_vector二维数组 c++ 用法-优快云博客
//初始化
vector<vector<int>> new_mat(r);//注意这个r是不可缺少的,规定其有多少行
for(int i=0 ;i<r; i++) //二维vector的初始化时有要求的
{
new_mat[i].resize(c);//规定每个一维数组大小
}//或者初始化
vector<vector<int>> new_mat(r, vector<int>(m, 0));
vector<vector<int>> new_mat(r, vector<int>(m));
//得到m*n矩阵的m
vector<vector<int>>matrix;
m = matrix.size();
n = matrix[0].size();
map和set
---------------------创建
set<int>s;
map<string,int>m;
---------------------插入
s.insert(10);
m["apple"] = 10;
or
m.insert({"banna",10});
--------------删除
s.erase(10);
s.erase(s.begin());
m.erase("apple");
---------------------查找
auto it = s.find(10);
if(it!=s.end()){//end指的是最后一个元素的下一位
找到啦!对于set,*it指的是指向的值;
对于map,指的是指向的键值对,即:
// 访问键(key) std::string key = it->first; // "apple" // 或者等价写法: std::string key = (*it).first; // "apple" // 访问值(value) int value = it->second; // 5 // 或者等价写法: int value = (*it).second; // 5
//set/map
的解引用得到的是const
元素(不可直接修改键it->first是键,不可以修改;it->second是值,可修改
it->second = 10;
}
-------------------------其他
s.size(); // 元素个数 s.empty(); // 是否为空 s.clear(); // 清空容器
1.
set
的典型用法
去重:
vector<int> v = {...}; set<int> s(v.begin(), v.end());//set没有重复值
存在性检查:
if (s.find(x) != s.end())
维护有序区间:合并区间、滑动窗口极值//???????
2.
map
的典型用法
字符频率统计:
string s = "hello"; map<char, int> freq; for (char c : s) freq[c]++;键值映射:缓存记录(如LRU Cache)、建立索引
替代大数组:当数据范围很大但稀疏时(如统计
1e9
范围内的出现次数)3.
unordered_map
的典型用法
快速查找:两数之和、子数组和为k
状态压缩:存储中间计算结果(如动态规划状态)
stl的begin/end
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> s = {1, 2, 3, 4, 5};
// 正向遍历
cout << "正向: ";
for (auto it = s.begin(); it != s.end(); ++it) {
cout << *it << " "; // 1 2 3 4 5
}
// 逆向遍历
cout << "\n逆向: ";
for (auto rit = s.rbegin(); rit != s.rend(); ++rit) {
cout << *rit << " "; // 5 4 3 2 1
}
return 0;
}
指针vs引用【还是不是很懂】
迭代器是对象or指针
stack
C++ stack使用方法详细介绍_c++ stack用法-优快云博客
#include<stack>
stack<int>st;
st.push(1);//添加栈顶元素
int a = st.top();//访问栈顶元素
st.pop();//移除栈顶元素
st.size();//元素个数
p.s.top,pop一般搭配着用,因为top只可以得到值,pop只可以移除值
队列
#include<queue>
#初始化
queue<int>q;
- push() 在队尾插入一个元素
- pop() 删除队列第一个元素
- size() 返回队列中元素个数
- empty() 如果队列空则返回true
- front() 返回队列中的第一个元素
- back() 返回队列中最后一个元素
结构体
构造函数
struct Point {
int x;
int y;
Point(int x_val, int y_val) : x(x_val), y(y_val) {} // 构造函数
};int main() {
Point p3(5, 6); // 调用构造函数
}
大括号初始化
struct Point {
int x;
int y;
};int main() {
Point p1 = {1, 2}; // 使用大括号初始化(聚合初始化)
}
struct数组定义和初始化
strcut Range{
int l;
int r;
Rage(int l,int r):l(l),r(r){}
bool opreator<(const Raneg &w){//为sort服务
return r<w.r;
}}Range[N];//
rangen];
在定义结构体的同时,声明了一个全局数组range
:
初始化
Range[i] = {a,b};
Range[i](a,b);
range[i] = Range{a, b};
或
range[i].l = a; range[i].r = b;
初始化【精华版】
#include <iostream>
// 有构造函数的版本
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode* next) : val(x), next(next) {}
};
// 无构造函数的版本(聚合类型)
struct SimpleNode {
int val;
SimpleNode* next;
};
int main() {
// -------------------------
// 有构造函数的初始化【圆括号】
// -------------------------
// 栈对象
ListNode n1(1); // 圆括号构造
ListNode n2{2}; // 花括号构造
// 堆对象
ListNode* pn3 = new ListNode(3); // 圆括号
ListNode* pn4 = new ListNode{4}; // 花括号(推荐)
// 链式结构
ListNode* head = new ListNode(0, new ListNode(1, nullptr));
// -------------------------
// 无构造函数的初始化【花括号】
// -------------------------
// 栈对象
SimpleNode sn1 = {5, nullptr}; // 列表初始化
SimpleNode sn2{6, nullptr}; // 花括号构造
// 堆对象
SimpleNode* psn3 = new SimpleNode{7, nullptr}; // 花括号
// 错误示例
// SimpleNode bad1(8); // ❌ 无构造函数不能用圆括号
// SimpleNode* bad2 = new SimpleNode(8); // ❌
// -------------------------
// 内存清理
// -------------------------
delete pn3;
delete pn4;
delete head;
delete psn3;
return 0;
}
重载运算符
sort(range, range + N); // 依赖重载的 < 运算符
ListNode* vs ListNode
#include <iostream>
#include <string>// 无构造函数的版本
struct DataWithoutCtor {
int id;
double value;
std::string name;
};// 有构造函数的版本
struct DataWithCtor {
int id;
double value;
std::string name;// 自定义构造函数
DataWithCtor(int i, double v, const std::string& n)
: id(i), value(v), name(n) {}
// 默认构造函数(可选)
DataWithCtor() : id(0), value(0.0), name("default") {}
};int main() {
// ------------------------
// 单个结构体对象初始化
// ------------------------
// 无构造函数:聚合初始化
DataWithoutCtor d1 = {1, 3.14, "Pi"};
DataWithoutCtor d2; // 警告:基本类型成员未初始化!// 有构造函数:必须使用构造函数
DataWithCtor d3(2, 2.718, "Euler");
DataWithCtor d4; // 需有默认构造函数// ------------------------
// 结构体数组初始化
// ------------------------
// 无构造函数:聚合初始化
DataWithoutCtor arr1[2] = {
{10, 1.1, "Alice"},
{20, 2.2, "Bob"}
};// 有构造函数:显式调用构造函数
DataWithCtor arr2[2] = {
DataWithCtor(30, 3.3, "Charlie"),
DataWithCtor(40, 4.4, "Diana")
};// C++11 统一初始化语法(推荐)
DataWithCtor arr3[]{
{50, 5.5, "Eric"}, // 隐式调用构造函数
{60, 6.6, "Fiona"}
};// ------------------------
// 赋值操作(有无构造函数均可)
// ------------------------
d1 = {100, 9.99, "Updated"}; // C++11 起支持
d3 = DataWithCtor(200, 8.88, "Replaced");return 0;
}