壹:考些什么 \texttt{壹:考些什么} 壹:考些什么
-
编程语言:
- 常见编程语言(C++)的基本语法和特性。
- 数据类型、变量、运算符、控制结构(如条件语句、循环语句)。
- 函数和过程的定义与调用、参数传递、作用域。
- 面向对象编程的基本概念,如类、对象、继承、多态等。
-
数据结构与算法:
- 常见数据结构的基本概念、特点和操作,如数组、链表、栈、队列、树、图等。
- 常见算法的基本原理和实现,如排序算法(如冒泡排序、快速排序、归并排序)、查找算法(如线性查找、二分查找)、递归算法、动态规划等。
- 数据结构与算法的分析和性能评估,如时间复杂度、空间复杂度。
-
操作系统:
- 操作系统的基本概念、功能和组成部分,如进程管理、内存管理、文件系统、设备管理等。
- 进程与线程的概念、创建与调度、同步与通信。
- 内存管理的基本原理,如虚拟内存、分页、分段等。
- 文件系统的组织结构、文件操作和权限管理等。
-
网络与数据库:
- 网络通信的基本概念和协议,如TCP/IP协议、HTTP协议等。
- 客户端与服务器的交互过程,如请求-响应模型、状态码、会话管理等。
- 数据库的基本概念和原理,如关系型数据库、SQL语句、索引、事务等。
-
软件工程:
- 软件开发的基本流程和方法,如需求分析、设计、编码、测试、部署等。
- 软件开发过程中的常见模型,如瀑布模型、敏捷开发等。
- 软件设计原则和设计模式,如单一职责原则、开闭原则、工厂模式、观察者模式等。
- 软件测试的基本概念和方法,如单元测试、集成测试、系统测试等。
贰:芝士点复习(c++算法) \texttt{贰:芝士点复习(c++算法)} 贰:芝士点复习(c++算法)
stl: \texttt{stl:} stl:
-
map \texttt{map} map(映射)是一种数据结构,它存储键值对,并根据给定的键来查找值。它的特征是键是唯一的,每个键对应一个值,而且可以根据键快速查找对应的值。在编程中, map \texttt{map} map通常被称为字典或关联数组。
-
stack \texttt{stack} stack(栈)是一种具有后进先出( LIFO \texttt{LIFO} LIFO)特性的数据结构。它的特征是只能在栈的顶部进行插入和删除操作,即最后插入的元素最先被删除。栈通常用于实现函数调用、表达式求值等场景。
-
list \texttt{list} list(列表)是一种有序的数据结构,它可以存储多个元素。列表的特征是元素的顺序是固定的,可以通过索引访问和修改元素。列表还支持动态调整大小,可以在任意位置插入和删除元素。
-
queue \texttt{queue} queue(队列)是一种具有先进先出(FIFO)特性的数据结构。它的特征是只能在队列的一端插入元素(称为队尾),在另一端删除元素(称为队头)。队列通常用于实现任务调度、消息传递等场景。
-
set \texttt{set} set(集合)是一种无序且不重复的数据结构,它存储唯一的元素。集合的特征是元素之间没有顺序关系,可以快速判断一个元素是否存在于集合中。集合通常用于去重、集合运算等场景。
-
deque \texttt{deque} deque(双端队列)是一种具有前后端插入和删除操作的数据结构。它的特征是可以在队列的两端进行插入和删除操作。双端队列通常用于实现双向搜索、缓存等场景。
其中的函数:
对于map(映射):
- insert(key, value):将键值对(key, value)插入到map中。
- erase(key):删除map中指定键的键值对。
- find(key):根据给定的键查找对应的值。
- size():返回map中键值对的数量。
对于stack(栈):
- push(element):将元素压入栈顶。
- pop():从栈顶弹出一个元素。
- top():返回栈顶元素的值。
- empty():检查栈是否为空。
- size():返回栈中元素的数量。
对于list(列表):
- push_back(element):将元素添加到列表的末尾。
- push_front(element):将元素添加到列表的开头。
- pop_back():删除列表末尾的元素。
- pop_front():删除列表开头的元素。
- size():返回列表中元素的数量。
- insert(position, element):在指定位置插入元素。
- erase(position):删除指定位置的元素。
- clear():清空列表中的所有元素。
对于queue(队列):
- push(element):将元素插入队列的末尾。
- pop():从队列的头部删除一个元素。
- front():返回队列头部的元素值。
- empty():检查队列是否为空。
- size():返回队列中元素的数量。
对于set(集合):
- insert(element):将元素插入集合中。
- erase(element):从集合中删除指定元素。
- find(element):查找集合中是否存在指定元素。
- size():返回集合中元素的数量。
对于deque(双端队列):
- push_back(element):将元素插入双端队列的末尾。
- push_front(element):将元素插入双端队列的开头。
- pop_back():从双端队列的末尾删除一个元素。
- pop_front():从双端队列的开头删除一个元素。
- size():返回双端队列中元素的数量。
对于vector(动态数组):
- push_back(element):将元素添加到vector的末尾。
- pop_back():删除vector末尾的元素。
- size():返回vector中元素的数量。
- empty():检查vector是否为空。
- at(index):返回指定索引位置的元素。
- insert(position, element):在指定位置插入元素。
- erase(position):删除指定位置的元素。
- clear():清空vector中的所有元素。
时间复杂度:
需省略常数 !
-
O ( 1 ) \mathcal{O}(1) O(1):常数时间复杂度,表示算法的运行时间不随输入规模的增长而变化。 n ≤ ∞ n\leq \infty n≤∞
-
O ( log n ) \mathcal{O}(\log n) O(logn):对数时间复杂度,表示算法的运行时间随输入规模的增长而以对数方式增长。 n ≤ 2 10 8 n\leq 2^{{10}^8} n≤2108
-
O ( n ) \mathcal{O}(n) O(n):线性时间复杂度,表示算法的运行时间与输入规模成线性关系。 n ≤ 100000000 n\leq 100000000 n≤100000000
-
O ( n log n ) \mathcal{O}(n\log n) O(nlogn):线性对数时间复杂度,表示算法的运行时间随输入规模的增长而以线性对数方式增长。 n ≤ 5000000 n\leq 5000000 n≤5000000
-
O ( n 2 ) \mathcal{O}(n^2) O(n2):平方时间复杂度,表示算法的运行时间与输入规模的平方成正比。 n ≤ 10000 n\leq 10000 n≤10000
-
O ( 2 n ) \mathcal{O}(2^n) O(2n):指数时间复杂度,表示算法的运行时间随输入规模的增长而呈指数级增长。 n ≤ 26 n\leq 26 n≤26
面向对象
-
类(Class):
类是一种用户定义的数据类型,用于封装数据和方法。它是对象的蓝图或模板,描述了对象的属性和行为。类的格式如下:
class ClassName {
private:
// 成员变量(属性)
// 成员函数(方法)
public:
// 公共成员变量(属性)
// 公共成员函数(方法)
};
类定义了对象的结构,可以包含成员变量和成员函数。私有成员(private)只能在类的内部访问,公共成员(public)可以在类的外部访问。
-
对象(Object):
对象是类的实例,通过实例化类创建。对象可以访问类中定义的成员变量和成员函数。对象的格式如下:ClassName objectName \texttt{ClassName objectName} ClassName objectName;
这里的 ClassName \texttt{ClassName} ClassName 是类的名称, objectName \texttt{objectName} objectName 是对象的名称。通过对象名和成员运算符.可以访问对象的成员。继承( Inheritance \texttt{Inheritance} Inheritance):
继承是一种机制,允许一个类(派生类)从另一个类(基类)继承属性和方法。派生类可以扩展基类的功能或重新定义基类的方法。继承的格式如下:
class DerivedClass : public BaseClass {
private:
// 派生类的成员变量(属性)
// 派生类的成员函数(方法)
public:
// 派生类的公共成员变量(属性)
// 派生类的公共成员函数(方法)
};
派生类通过关键字 $\texttt{public}$ 继承基类的公共成员。私有成员不会被派生类继承,但可以通过基类的公共成员函数访问。
- 多态(
Polymorphism
\texttt{Polymorphism}
Polymorphism):
多态是一种特性,允许使用基类指针或引用来操作派生类对象,实现不同对象之间的统一接口。多态可以通过虚函数实现,虚函数允许在派生类中重新定义基类的方法。多态的格式如下:
class BaseClass {
public:
virtual void virtualFunction() {
// 基类方法的实现
}
};
class DerivedClass : public BaseClass {
public:
void virtualFunction() override {
// 派生类方法的实现
}
};
在基类的方法声明中使用关键字 $\texttt{virtual}$,并在派生类中使用关键字 $\texttt{override}$ 重新定义方法。通过基类指针或引用调用虚函数时,会根据对象的实际类型来调用相应的方法。
- 构造函数(
Constructor
\texttt{Constructor}
Constructor):
构造函数是一种特殊的成员函数,用于初始化对象的数据成员。构造函数的名称与类名相同,没有返回类型。它会在创建对象时自动调用。构造函数的格式如下:
ClassName() {
// 构造函数的实现
}
构造函数可以有参数,用于在创建对象时传递初始化数据。
- 析构函数(
Destructor
\texttt{Destructor}
Destructor):
析构函数是一种特殊的成员函数,用于在对象销毁时进行清理工作。析构函数的名称与类名相同,前面加上波浪号~作为前缀。它没有参数和返回类型。析构函数的格式如下:
~ClassName() {
// 析构函数的实现
}
析构函数会在对象销毁时自动调用,用于释放对象占用的资源。
排序:
各种排序的模板:
冒泡排序(Bubble Sort) O ( n 2 ) \mathcal O (n^2) O(n2):
template<typename T>
void bubbleSort(T arr[], int size) {
for (int i = 0; i < size - 1; ++i) {
for (int j = 0; j < size - i - 1; ++j) {
if (arr[j] > arr[j + 1]) {
std::swap(arr[j], arr[j + 1]);
}
}
}
}
插入排序(Insertion Sort) O ( n 2 ) \mathcal O (n^2) O(n2):
template<typename T>
void insertionSort(T arr[], int size) {
for (int i = 1; i < size; ++i) {
T key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
--j;
}
arr[j + 1] = key;
}
}
选择排序(Selection Sort) O ( n 2 ) \mathcal O (n^2) O(n2):
template<typename T>
void selectionSort(T arr[], int size) {
for (int i = 0; i < size - 1; ++i) {
int minIndex = i;
for (int j = i + 1; j < size; ++j) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
std::swap(arr[i], arr[minIndex]);
}
}
快速排序(Quick Sort) O ( n log n ) \mathcal O (n \log n) O(nlogn):
template<typename T>
int partition(T arr[], int low, int high) {
T pivot = arr[high];
int i = low - 1;
for (int j = low; j <= high - 1; ++j) {
if (arr[j] < pivot) {
++i;
std::swap(arr[i], arr[j]);
}
}
std::swap(arr[i + 1], arr[high]);
return i + 1;
}
template<typename T>
void quickSort(T arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
(快速排序)不建议按上述代码写,应使用 (stl)sort
时间复杂度:
O
(
n
log
n
)
\mathcal O (n \log n)
O(nlogn)。
二分:
二分算法的时间复杂度是 O ( log n ) O(\log n) O(logn),其中 n n n表示要进行二分查找的数据规模。二分算法适用于已排序的数据集合,并且可以快速定位目标元素的位置。它的使用场景包括:
-
查找:当数据集合已排序时,可以使用二分算法在 O ( log n ) O(\log n) O(logn)的时间复杂度内查找目标元素的位置。
-
边界问题:可以使用二分算法来查找满足某个条件的边界值,例如最小值、最大值或满足特定条件的第一个或最后一个元素。
-
数值范围搜索:在某个数值范围内搜索满足特定条件的元素。
-
前提:必须要具备函数的单调性(即 x x x 越大, a n s ans ans 越小 / / / 大)
// 二分答案模板
int l, r, ans;
while (l <= r)
{
int mid = (l + r) >> 1;
if (check(mid))
l = mid + 1, ans = mid;
else
r = mid - 1;
}
// 或者
int l, r, ans;
while (l <= r)
{
int mid = (l + r) >> 1;
if (check(mid))
r = mid - 1, ans = mid;
else
l = mid + 1;
}
动态规划:
-
背包问题:背包问题是动态规划中的一个经典问题。它通常描述了一个背包的最大容量和一组物品的重量和价值,目标是在不超过背包容量的情况下,选择一些物品放入背包,使得物品的总价值最大化。背包问题可以分为 0 / 1 0/1 0/1背包问题(每个物品要么放入背包要么不放入)和完全背包问题(每个物品可以无限次放入背包)。
-
状态转移方程:动态规划通过定义状态和状态之间的转移关系来解决问题。状态转移方程描述了当前状态与之前状态之间的关系。对于背包问题,状态转移方程通常表示在考虑当前物品时,选择放入背包或不放入背包的决策。
-
时间复杂度:动态规划的时间复杂度取决于问题的规模和状态转移的计算量。通常情况下,动态规划的时间复杂度是 O ( n m ) \mathcal O(nm) O(nm),其中 n n n是问题的规模, m m m是状态的个数。但是,有些问题可能具有更高的时间复杂度,需要进行优化。
-
子类型:动态规划问题可以分为多个子类型,例如线性动态规划、区域动态规划、树形动态规划等。每个子类型都有其特定的特征和解决方法。线性动态规划适用于线性序列上的问题,区域动态规划适用于二维区域上的问题,树形动态规划适用于树结构上的问题等。
移位:
-
左移操作(
<<
):左移操作将一个二进制数值的所有位向左移动指定的位数。在左移过程中,最左边的位将被丢弃,右边用 0 0 0 填充。左移操作可以看作是将一个数乘以 2 2 2 的幂次方。例如,对于 ( 1010 ) 2 (1010)_2 (1010)2,左移一位变为 ( 10100 ) 2 (10100)_2 (10100)2 ,相当于将十进制数 10 10 10 左移一位变为 20 20 20 。 -
右移操作(
>>
):右移操作将一个二进制数值的所有位向右移动指定的位数。在右移过程中,最右边的位将被丢弃,左边用符号位(对于有符号数)或 0 0 0填充。右移操作可以看作是将一个数除以 2 2 2的幂次方并向下取整。例如,对于 ( 1010 ) 2 (1010)_2 (1010)2,右移一位变为 ( 0101 ) 2 (0101)_2 (0101)2,相当于将十进制数 10 10 10右移一位变为 5 5 5。
移位操作在计算机编程中具有广泛的应用。它可以用于对数据进行快速的乘法和除法运算,以及对二进制位的处理和控制。在某些情况下,移位操作还可以用于优化算法和数据结构的实现。
补充:
移位可能会丢失精度。有时vector<vector<int>>
在 c++ 中会将int>>
识别成右移,所以最好加一个 可爱的 空格。
叁:计算机 \texttt{叁:计算机} 叁:计算机
计算机是一种电子设备,用于处理和存储数据,执行各种计算和操作。它由硬件和软件两部分组成。
-
硬件:计算机的硬件包括中央处理器(CPU)、内存、存储设备(如硬盘和固态硬盘)、输入设备(如键盘和鼠标)、输出设备(如显示器和打印机)以及各种接口和总线连接它们。CPU是计算机的核心部件,负责执行指令和进行计算。内存用于临时存储数据和程序。存储设备用于长期存储数据和程序。
-
软件:计算机的软件是指安装在计算机上的程序和数据。软件分为系统软件和应用软件。系统软件包括操作系统、编译器、驱动程序等,用于管理和控制计算机的硬件资源。应用软件是根据用户需求开发的各种应用程序,例如办公软件、游戏、图像处理软件等。
计算机通过执行一系列指令来完成各种任务。指令是以二进制形式表示的机器代码,由计算机的CPU执行。CPU根据指令集架构(如x86、ARM等)来理解和执行指令。
计算机工作的基本原理是将数据加载到内存中,然后通过CPU对数据进行处理和计算。计算机通过输入设备接收用户的指令和数据,通过输出设备向用户显示结果。
计算机的发展经历了几个重要阶段,从大型机到微型机,再到现代的个人电脑、笔记本电脑、智能手机和其他嵌入式系统。计算机的性能不断提高,体积不断缩小,功能不断扩展,已经成为现代社会不可或缺的工具。
第一台计算机: 1946 1946 1946年 ENIAC \texttt{ENIAC} ENIAC
计算机之父:冯·诺依曼 匈牙利
人工智能之父:图灵 英国
冯·诺依曼理论计算机:输入设备,运算器,存储器,控制器,输出设备
第一个程序员: Ada Lovelace
肆:操作系统 \texttt{肆:操作系统} 肆:操作系统
Operating System
-
操作系统的基本概念:
- 操作系统是计算机系统中的核心软件,负责管理和控制计算机的硬件和软件资源。
- 它为用户和应用程序提供一个统一的接口和环境,使得用户可以方便地使用计算机系统。
-
操作系统的功能:
- 进程管理:负责创建、调度和管理进程,控制进程的执行和资源分配。
- 内存管理:负责管理计算机的内存资源,包括内存分配、内存保护和虚拟内存等。
- 文件系统:负责管理计算机的文件系统,包括文件的组织结构、文件的读写操作和权限管理等。
- 设备管理:负责管理计算机的硬件设备和设备驱动程序,控制设备的输入和输出。
-
进程与线程的概念:
- 进程是正在执行的程序的实例,它具有独立的内存空间和资源。
- 线程是进程中的一个执行单元,多个线程可以共享同一个进程的资源。
-
进程与线程的创建与调度:
- 进程的创建与调度由操作系统负责,通过系统调用来创建新的进程。
- 线程的创建与调度由线程库或操作系统提供的线程管理机制来实现。
-
进程与线程的同步与通信:
- 进程间的同步和通信可以通过共享内存、消息传递、信号量等机制来实现。
- 线程间的同步和通信可以通过互斥锁、条件变量、信号量等机制来实现。
-
内存管理的基本原理:
- 虚拟内存:将物理内存和磁盘空间结合起来,提供更大的地址空间。
- 分页:将物理内存和进程的地址空间划分为固定大小的页面,实现虚拟内存的映射。
- 分段:将进程的地址空间划分为若干个段,每个段具有不同的属性和大小。
-
文件系统的组织结构:
- 文件系统由文件、目录和文件描述符等组成,用于管理和组织文件。
- 文件系统可以采用层次结构、索引结构、位图等方式来组织文件和目录。
-
文件操作和权限管理:
- 文件操作包括创建、读取、写入和删除文件等操作。
- 权限管理用于控制对文件的访问权限,包括读取、写入和执行等权限。
伍:网络 & 数据库 \texttt{伍:网络 \& 数据库} 伍:网络 & 数据库
-
网络通信的基本概念和协议:
- 网络通信是指在计算机网络中,不同设备之间进行数据传输和交流的过程。
- TCP/IP协议是互联网通信的基础协议,它包括传输控制协议(TCP)和网络互联协议(IP)等多个协议。
- HTTP协议(超文本传输协议)是一种用于在Web浏览器和Web服务器之间传输数据的协议。
-
客户端与服务器的交互过程:
- 请求-响应模型:客户端发送请求到服务器,服务器处理请求并返回响应给客户端。
- 状态码:服务器返回的响应中包含状态码,用于表示请求的处理结果,如200表示成功,404表示资源未找到等。
- 会话管理:服务器通过会话管理机制来跟踪和管理客户端与服务器之间的交互状态,常见的机制包括Cookie和Session。
-
数据库的基本概念和原理:
- 关系型数据库:基于关系模型的数据库,使用表格(关系)来存储和组织数据,如MySQL、Oracle等。
- SQL语句:结构化查询语言,用于在关系型数据库中进行数据查询、插入、更新和删除等操作。
- 索引:用于提高数据库查询效率的数据结构,可以加速数据检索操作。
- 事务:数据库事务是一组数据库操作的逻辑单元,要么全部执行成功,要么全部回滚,保证数据的一致性和完整性。
陆:软件工程 \texttt{陆:软件工程} 陆:软件工程
-
软件开发的基本流程和方法:
- 需求分析:确定用户需求和系统功能。
- 设计:根据需求设计系统架构和模块。
- 编码:根据设计编写代码。
- 测试:对代码进行测试,包括单元测试、集成测试和系统测试等。
- 部署:将软件部署到目标环境中,进行安装和配置。
-
软件开发过程中的常见模型:
- 瀑布模型:按照线性顺序依次进行需求分析、设计、编码、测试和部署等阶段。
- 敏捷开发:采用迭代和增量的方式进行开发,强调快速响应变化和持续交付。
-
软件设计原则和设计模式:
- 单一职责原则:一个类应该只有一个引起它变化的原因。
- 开闭原则:软件实体应该对扩展开放,对修改关闭。
- 工厂模式:通过工厂类来创建对象,隐藏对象的具体实现细节。
- 观察者模式:定义了一种一对多的依赖关系,当一个对象状态发生变化时,其依赖的对象会自动收到通知。
-
软件测试的基本概念和方法:
- 单元测试:对软件的最小可测试单元进行测试,通常是函数或方法。
- 集成测试:将多个模块或组件进行集成,测试它们之间的接口和协作。
- 系统测试:对整个系统进行测试,验证系统是否满足需求和用户期望。