解决合并冲突

This commit is contained in:
big 2024-09-13 13:43:10 +08:00
commit 3948d3c00e
20 changed files with 1307 additions and 88 deletions

View File

@ -4,7 +4,7 @@
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.venv" />
</content>
<orderEntry type="jdk" jdkName="Python 3.10" jdkType="Python SDK" />
<orderEntry type="jdk" jdkName="Python 3.12 (doc) (2)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -3,5 +3,5 @@
<component name="Black">
<option name="sdkName" value="Python 3.12 (doc)" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (doc) (2)" project-jdk-type="Python SDK" />
</project>

View File

@ -9,7 +9,7 @@
- 环境安装
``` python
pip install -r requirements.txt
```
```
- 运行start.py
@ -29,4 +29,4 @@ $ mkdocs serve # 在本地启动服务器预览
- 在工单中提交需求
- 联系我:sairate@sina.cn
![issues](.\static\image\issues.jpg)
![issues](/static/image/issues.jpg)

View File

@ -1,3 +1,4 @@
@@ -1,29 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
@ -93,3 +94,93 @@
+ </component>
</project>
\ No newline at end of file
=======
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="eb8b4e81-1a37-4d94-9efb-d5d51fd6cfbd" name="更改" comment="">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
<component name="ProjectColorInfo">{
&quot;associatedIndex&quot;: 3
}</component>
<component name="ProjectId" id="2ldbjkIndUDrjuY9k9E4B74huNw" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;master&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
}
}</component>
<component name="RunManager">
<configuration name="start" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
<module name="notebook" />
<option name="ENV_FILES" value="" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" />
<envs>
<env name="PYTHONUNBUFFERED" value="1" />
</envs>
<option name="SDK_HOME" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="IS_MODULE_SDK" value="true" />
<option name="ADD_CONTENT_ROOTS" value="true" />
<option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/start.py" />
<option name="PARAMETERS" value="" />
<option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" />
<option name="REDIRECT_INPUT" value="false" />
<option name="INPUT_FILE" value="" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Python.start" />
</list>
</recent_temporary>
</component>
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="bundled-python-sdk-50da183f06c8-2887949eec09-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-233.13135.95" />
</set>
</attachedChunks>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="应用程序级" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="默认任务">
<changelist id="eb8b4e81-1a37-4d94-9efb-d5d51fd6cfbd" name="更改" comment="" />
<created>1725513042181</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1725513042181</updated>
<workItem from="1725518275042" duration="21000" />
<workItem from="1725532958825" duration="34000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
</project>

View File

@ -0,0 +1,28 @@
1. `cout`: 用于标准输出,可以使用`<<`操作符将数据输出到屏幕上。
```cpp
std::cout << "Hello, world!" << std::endl;
```
2. `cin`: 用于标准输入,可以使用`>>`操作符从用户输入中读取数据。
```cpp
int num;
std::cin >> num;
```
3. `endl`: 输出换行符并刷新输出缓冲区。
```cpp
std::cout << "Hello" << std::endl;
```
4. `cerr`: 用于输出错误信息,通常用于标准错误流。
```cpp
std::cerr << "Error: something went wrong!" << std::endl;
```
5. `fixed`和`setprecision`: 用于控制浮点数的输出精度。
```cpp
double num = 3.14159;
std::cout << std::fixed << std::setprecision(2) << num << std::endl;
```

View File

@ -0,0 +1,89 @@
1. **查找和比较**
- `find`:在范围内查找元素。
- `find_if`:在范围内查找满足指定条件的元素。
- `count`:统计范围内满足条件的元素个数。
- `count_if`:统计范围内满足指定条件的元素个数。
- `equal`:比较两个范围是否相等。
- `lexicographical_compare`:按字典序比较两个范围。
```cpp
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
vector<int> vec = {1, 2, 3, 4, 5};
// 查找元素
auto it = find(vec.begin(), vec.end(), 3);
if (it != vec.end()) {
cout << "Element found: " << *it << endl;
}
// 查找满足条件的元素
auto it2 = find_if(vec.begin(), vec.end(), [](int x) { return x > 3; });
if (it2 != vec.end()) {
cout << "Element > 3 found: " << *it2 << endl;
}
// 统计元素个数
int num = count(vec.begin(), vec.end(), 2);
cout << "Number of 2s: " << num << endl;
// 比较两个范围
vector<int> vec2 = {1, 2, 3};
bool result = equal(vec.begin(), vec.end(), vec2.begin(), vec2.end());
if (result) {
cout << "Vectors are equal" << endl;
} else {
cout << "Vectors are not equal" << endl;
}
return 0;
}
```
2. **排序和操作**
- `sort`:对范围内的元素进行排序。
- `reverse`:反转范围内的元素顺序。
- `copy`:将范围内的元素复制到另一个位置。
- `remove`:移除范围内满足条件的元素(不会改变容器大小)。
- `remove_if`:移除范围内满足指定条件的元素(不会改变容器大小)。
- `transform`:对范围内的元素执行指定操作。
```cpp
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
vector<int> vec = {5, 3, 1, 4, 2};
// 排序
sort(vec.begin(), vec.end());
// 反转元素顺序
reverse(vec.begin(), vec.end());
// 复制元素到另一个位置
vector<int> vec2(5);
copy(vec.begin(), vec.end(), vec2.begin());
// 移除元素
vec.erase(remove(vec.begin(), vec.end(), 3), vec.end());
// 对元素执行操作
transform(vec.begin(), vec.end(), vec.begin(), [](int x) { return x * 2; });
// 输出元素
for (auto& num : vec) {
cout << num << " ";
}
cout << endl;
return 0;
}
```

View File

@ -0,0 +1,87 @@
1. `std::ifstream`: 用于从文件中读取数据的输入流对象。常用的成员函数包括:
- `open(const char* filename)`: 打开指定文件名的文件。
- `close()`: 关闭文件。
- `is_open()`: 判断文件是否已经打开。
- `good()`: 判断文件流状态是否良好。
```cpp
#include <fstream>
#include <iostream>
int main() {
std::ifstream inputFile;
inputFile.open("input.txt");
if (inputFile.is_open()) {
std::cout << "File opened successfully." << std::endl;
// 读取文件内容
std::string line;
while (std::getline(inputFile, line)) {
std::cout << line << std::endl;
}
inputFile.close();
} else {
std::cerr << "Unable to open file." << std::endl;
}
return 0;
}
```
2. `std::ofstream`: 用于向文件中写入数据的输出流对象。常用的成员函数包括:
- `open(const char* filename)`: 创建或打开指定文件名的文件。
- `close()`: 关闭文件。
- `is_open()`: 判断文件是否已经打开。
- `good()`: 判断文件流状态是否良好。
```cpp
#include <fstream>
#include <iostream>
int main() {
std::ofstream outputFile;
outputFile.open("output.txt");
if (outputFile.is_open()) {
std::cout << "File opened successfully." << std::endl;
// 写入数据到文件
outputFile << "Hello, world!" << std::endl;
outputFile << 42 << std::endl;
outputFile.close();
} else {
std::cerr << "Unable to open file." << std::endl;
}
return 0;
}
```
3. `std::fstream`: 同时支持读写操作的文件流对象。常用的成员函数包括:
- `open(const char* filename, std::ios_base::openmode mode)`: 打开指定文件名的文件,并指定打开模式(例如`std::ios::in`表示读取模式,`std::ios::out`表示写入模式)。
- `close()`: 关闭文件。
- `is_open()`: 判断文件是否已经打开。
- `good()`: 判断文件流状态是否良好。
```cpp
#include <fstream>
#include <iostream>
int main() {
std::fstream file;
file.open("data.txt", std::ios::out | std::ios::app);
if (file.is_open()) {
std::cout << "File opened successfully." << std::endl;
// 写入数据到文件
file << "Appended line." << std::endl;
file.close();
} else {
std::cerr << "Unable to open file." << std::endl;
}
return 0;
}
```
这些函数和对象使得在C++中进行文件输入输出操作变得简单和方便。

View File

@ -0,0 +1,76 @@
1. `std::string`: C++中的字符串类,提供了丰富的成员函数用于字符串操作。常用的成员函数包括:
- `size()`: 返回字符串的长度。
- `length()`: 返回字符串的长度。
- `empty()`: 判断字符串是否为空。
- `clear()`: 清空字符串内容。
- `substr(pos, len)`: 返回从位置`pos`开始长度为`len`的子字符串。
- `find(str, pos)`: 在字符串中查找子字符串`str`,并返回第一次出现的位置。
- `replace(pos, len, str)`: 替换字符串中从位置`pos`开始长度为`len`的子串为字符串`str`。
- `append(str)`: 在字符串末尾追加字符串`str`。
- `insert(pos, str)`: 在指定位置插入字符串`str`。
```cpp
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, world!";
// 使用成员函数进行字符串操作
std::cout << "Length: " << str.length() << std::endl;
std::cout << "Substring: " << str.substr(0, 5) << std::endl;
str.replace(7, 5, "C++");
std::cout << "Replaced: " << str << std::endl;
str.append(" Goodbye!");
std::cout << "Appended: " << str << std::endl;
str.insert(0, "Greetings, ");
std::cout << "Inserted: " << str << std::endl;
return 0;
}
```
2. `std::getline()`: 从输入流中读取一行数据并存储到字符串中。
```cpp
#include <iostream>
#include <string>
int main() {
std::string line;
std::cout << "Enter a line of text: ";
std::getline(std::cin, line);
std::cout << "You entered: " << line << std::endl;
return 0;
}
```
3. 字符串查找和比较函数:
- `std::string::find(str, pos)`: 在字符串中查找子字符串`str`,并返回第一次出现的位置。
- `std::string::rfind(str, pos)`: 在字符串中从后向前查找子字符串`str`,并返回第一次出现的位置。
- `std::string::find_first_of(str, pos)`: 在字符串中查找任意字符集合`str`中的字符,返回第一次出现的位置。
- `std::string::find_last_of(str, pos)`: 在字符串中从后向前查找任意字符集合`str`中的字符,返回第一次出现的位置。
- `std::string::compare(str)`: 比较字符串与`str`返回大小关系0表示相等负数表示小于正数表示大于
```cpp
#include <iostream>
#include <string>
int main() {
std::string str = "Hello, world!";
if (str.find("world") != std::string::npos) {
std::cout << "Substring found!" << std::endl;
}
if (str.compare("Hello, C++!") == 0) {
std::cout << "Strings are equal." << std::endl;
}
return 0;
}
```

View File

@ -0,0 +1,43 @@
1. `time_t time(time_t* timer)`: 返回当前的日历时间作为一个 `time_t` 对象。如果 `timer` 不是 NULL则结果也存储在 `timer` 指向的变量中。
2. `struct tm *localtime(const time_t* timer)`: 将日历时间 `timer` 转换为本地时间表示(`struct tm`),包括年、月、日、时、分和秒等字段。
3. `struct tm *gmtime(const time_t* timer)`: 类似于 `localtime`,但它将日历时间 `timer` 转换为协调世界时UTC
4. `time_t mktime(struct tm* timeptr)`: 将表示日历时间的 `struct tm` 对象转换为 `time_t` 对象。
5. `char* asctime(const struct tm* timeptr)`: 将 `struct tm` 对象转换为人类可读的字符串,表示日期和时间的格式为 "Www Mmm dd hh:mm:ss yyyy\n",其中 Www 是星期几Mmm 是月份dd 是日期hh:mm:ss 是时间yyyy 是年份。
6. `char* ctime(const time_t* timer)`: 等同于 `asctime(localtime(timer))`。它将 `time_t` 对象转换为人类可读的字符串,表示本地时间。
7. `clock_t clock(void)`: 返回程序自执行开始以来或上一次调用 `clock()` 以来消耗的处理器时间。返回的值以时钟滴答数表示,可以使用 `CLOCKS_PER_SEC` 将其转换为秒。
```c++
#include <iostream>
#include <ctime>
int main() {
// 获取当前时间
time_t now = time(0);
std::cout << "当前时间为:" << ctime(&now);
// 将当前时间转换为本地时间
struct tm *localTime = localtime(&now);
std::cout << "本地时间为:" << asctime(localTime);
// 将当前时间转换为UTC时间
struct tm *utcTime = gmtime(&now);
std::cout << "UTC时间为" << asctime(utcTime);
// 将本地时间结构体转换为时间戳
time_t localTimestamp = mktime(localTime);
std::cout << "本地时间的时间戳为:" << localTimestamp << std::endl;
// 测量程序执行时间
clock_t start = clock();
for (int i = 0; i < 1000000; ++i) {
// 一些计算任务
}
clock_t end = clock();
double elapsedSeconds = double(end - start) / CLOCKS_PER_SEC;
std::cout << "程序执行时间为:" << elapsedSeconds << " " << std::endl;
return 0;
}
```

View File

@ -0,0 +1,58 @@
1. **时长类型**
- `std::chrono::duration`:表示时间段。例如,`std::chrono::duration<int>` 表示基于整数的时间段,而 `std::chrono::duration<double>` 表示基于浮点数的时间段。
- `std::chrono::hours`、`std::chrono::minutes`、`std::chrono::seconds`、`std::chrono::milliseconds`、`std::chrono::microseconds`、`std::chrono::nanoseconds`:具有不同单位的特定时长类型。
2. **时间点类型**
- `std::chrono::time_point`:表示时间点。它在时钟类型和时长类型上进行模板化。
- `std::chrono::system_clock`、`std::chrono::steady_clock`、`std::chrono::high_resolution_clock``<chrono>` 提供的时钟类型。
3. **时钟函数**
- `std::chrono::duration_cast`:将一个时长转换为具有不同刻度的另一个时长。
- `std::chrono::time_point_cast`:将一个时间点转换为具有不同时钟的另一个时间点。
- `std::chrono::system_clock::now()`:根据系统时钟获取当前时间。
- `std::chrono::steady_clock::now()`:根据稳定时钟(单调时钟)获取当前时间。
- `std::chrono::high_resolution_clock::now()`:如果可用,根据高分辨率时钟获取当前时间。
4. **实用函数**
- `std::chrono::duration_values`:提供时长类型的最小值和最大值。
- `std::chrono::time_point::min()`、`std::chrono::time_point::max()`:返回时间点类型的最小值和最大值。
5. **算术运算**
- 时长类型支持算术运算,如加法(`operator+`)、减法(`operator-`)、乘法(`operator*`)、除法(`operator/`)以及比较运算(`operator==`、`operator!=`、`operator<` 等)。
6. **时长字面值**
- 可以使用字面值后缀,如 `h`、`min`、`s`、`ms`、`us`、`ns` 来创建时长字面值。例如,`5s` 表示 5 秒。
这里是一个简单的示例,演示了这些功能:
```cpp
#include <iostream>
#include <chrono>
int main() {
using namespace std::chrono;
// 定义时长
auto 秒 = seconds(10);
auto 毫秒 = 5ms;
// 添加时长
auto 总时长 = 秒 + 毫秒;
// 获取当前时间点
auto 开始 = steady_clock::now();
// 等待 2 秒
std::this_thread::sleep_for(2s);
// 计算经过的时间
auto 结束 = steady_clock::now();
auto 经过时间 = duration_cast<seconds>(结束 - 开始);
std::cout << "总时长:" << 总时长.count() << " 毫秒\n";
std::cout << "经过时间:" << 经过时间.count() << " \n";
return 0;
}
```

View File

@ -0,0 +1,82 @@
1. **构造函数**
- `vector<T>`:创建一个空的向量,元素类型为 `T`
- `vector<T>(size_type count)`:创建包含 `count` 个默认构造的元素的向量。
- `vector<T>(size_type count, const T& value)`:创建包含 `count` 个值为 `value` 的元素的向量。
- `vector<T>(InputIterator first, InputIterator last)`:使用迭代器范围 `[first, last)` 中的元素创建向量。
2. **元素访问**
- `vector::operator[]`:通过索引访问元素。
- `vector::at(size_type pos)`:通过位置访问元素,如果越界会抛出 `std::out_of_range` 异常。
- `vector::front()`:返回第一个元素的引用。
- `vector::back()`:返回最后一个元素的引用。
- `vector::data()`:返回指向底层数据的指针。
3. **迭代器**
- `vector::begin()`:返回指向第一个元素的迭代器。
- `vector::end()`:返回指向最后一个元素后面位置的迭代器。
- `vector::rbegin()`:返回指向最后一个元素的逆向迭代器。
- `vector::rend()`:返回指向第一个元素前面位置的逆向迭代器。
4. **容量**
- `vector::size()`:返回向量中元素的数量。
- `vector::max_size()`:返回向量能容纳的最大元素数量。
- `vector::empty()`:检查向量是否为空。
- `vector::reserve(size_type new_cap)`:为向量预留至少能容纳 `new_cap` 个元素的空间。
- `vector::capacity()`:返回向量当前能容纳的元素数量。
5. **修改容器**
- `vector::push_back(const T& value)`:在向量末尾添加一个元素。
- `vector::pop_back()`:移除向量末尾的元素。
- `vector::insert(iterator pos, const T& value)`:在指定位置插入一个元素。
- `vector::erase(iterator pos)`:移除指定位置的元素。
- `vector::clear()`:清空向量中的所有元素。
6. **比较**
- `vector::operator==`、`vector::operator!=`、`vector::operator<`、`vector::operator<=`、`vector::operator>`、`vector::operator>=`:用于比较两个向量的操作符。
7. **其他操作**
- `vector::swap(vector& other)`:交换两个向量的内容。
- `vector::emplace_back(Args&&... args)`:在向量末尾构造一个元素。
- `vector::shrink_to_fit()`:将向量的容量调整为其当前元素数量。
```c++
#include <iostream>
#include <vector>
int main() {
// 创建一个空的整数向量
std::vector<int> numbers;
// 在向量末尾添加元素
numbers.push_back(10);
numbers.push_back(20);
numbers.push_back(30);
// 使用迭代器遍历向量并输出元素
std::cout << "Vector elements:";
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
std::cout << " " << *it;
}
std::cout << std::endl;
// 访问向量的第一个和最后一个元素
std::cout << "First element: " << numbers.front() << std::endl;
std::cout << "Last element: " << numbers.back() << std::endl;
// 检查向量是否为空
std::cout << "Is the vector empty? " << (numbers.empty() ? "Yes" : "No") << std::endl;
// 获取向量的大小和容量
std::cout << "Vector size: " << numbers.size() << std::endl;
std::cout << "Vector capacity: " << numbers.capacity() << std::endl;
// 清空向量
numbers.clear();
std::cout << "Vector size after clear: " << numbers.size() << std::endl;
return 0;
}
```

150
notebook/docs/C++/7.list.md Normal file
View File

@ -0,0 +1,150 @@
1. **构造函数**
- `list()`:创建一个空链表。
- `list(const list& other)`:拷贝构造函数,用另一个链表初始化当前链表。
2. **赋值和交换**
- `operator=`:将一个链表赋值给另一个链表。
- `assign`:用特定数量的元素或范围内的元素替换链表的内容。
- `swap`:交换两个链表的内容。
3. **迭代器相关**
- `begin`:返回指向第一个元素的迭代器。
- `end`:返回指向最后一个元素之后的位置的迭代器。
- `rbegin`:返回指向最后一个元素的反向迭代器。
- `rend`:返回指向第一个元素之前的位置的反向迭代器。
4. **容量**
- `empty`:判断链表是否为空。
- `size`:返回链表中元素的数量。
- `max_size`:返回链表最大可容纳的元素数量。
5. **访问元素**
- `front`:返回第一个元素的引用。
- `back`:返回最后一个元素的引用。
6. **修改容器**
- `push_front`:在链表的开头插入一个元素。
- `pop_front`:移除链表的第一个元素。
- `push_back`:在链表的末尾插入一个元素。
- `pop_back`:移除链表的最后一个元素。
- `insert`:在指定位置插入一个或多个元素。
- `erase`:移除指定位置或范围内的一个或多个元素。
- `clear`:移除链表的所有元素。
7. **其他操作**
- `splice`:将另一个链表的元素移动到当前链表的指定位置。
- `merge`:将两个有序链表合并为一个有序链表。
- `sort`:对链表进行排序。
- `reverse`:反转链表中的元素顺序。
1. **构造函数**
```cpp
#include <iostream>
#include <list>
using namespace std;
int main() {
// 创建空链表
list<int> mylist;
// 用另一个链表初始化当前链表
list<int> otherlist = {1, 2, 3};
list<int> mylist2(otherlist);
return 0;
}
```
2. **赋值和交换**
```cpp
// 赋值
mylist = otherlist;
// 用特定数量的元素或范围内的元素替换链表的内容
mylist.assign(5, 10); // 用5个值为10的元素替换mylist的内容
// 交换两个链表的内容
mylist.swap(otherlist);
```
3. **迭代器相关**
```cpp
// 使用迭代器访问元素
list<int>::iterator it = mylist.begin();
for (; it != mylist.end(); ++it) {
cout << *it << " ";
}
```
4. **容量**
```cpp
// 判断链表是否为空
if (mylist.empty()) {
cout << "链表为空" << endl;
}
// 返回链表中元素的数量
cout << "链表中元素的数量:" << mylist.size() << endl;
```
5. **访问元素**
```cpp
// 返回第一个元素的引用
int firstElement = mylist.front();
// 返回最后一个元素的引用
int lastElement = mylist.back();
```
6. **修改容器**
```cpp
// 在链表的开头插入一个元素
mylist.push_front(100);
// 移除链表的第一个元素
mylist.pop_front();
// 在链表的末尾插入一个元素
mylist.push_back(200);
// 移除链表的最后一个元素
mylist.pop_back();
// 在指定位置插入一个或多个元素
list<int>::iterator it = mylist.begin();
advance(it, 2); // 移动迭代器到第三个位置
mylist.insert(it, 777);
// 移除指定位置或范围内的一个或多个元素
it = mylist.begin();
advance(it, 1); // 移动迭代器到第二个位置
mylist.erase(it);
// 移除链表的所有元素
mylist.clear();
```
7. **其他操作**
```cpp
// 将另一个链表的元素移动到当前链表的指定位置
list<int> anotherlist = {9, 8, 7};
list<int>::iterator pos = mylist.begin();
advance(pos, 2); // 移动到第三个位置
mylist.splice(pos, anotherlist);
// 将两个有序链表合并为一个有序链表
list<int> sortedlist1 = {1, 3, 5};
list<int> sortedlist2 = {2, 4, 6};
sortedlist1.merge(sortedlist2);
// 对链表进行排序
mylist.sort();
// 反转链表中的元素顺序
mylist.reverse();
```

View File

@ -0,0 +1,68 @@
1. **构造函数**
- `map()`:创建一个空的映射容器。
- `map(const map& other)`:拷贝构造函数,用另一个映射容器初始化当前映射容器。
2. **赋值和交换**
- `operator=`:将一个映射容器赋值给另一个映射容器。
- `assign`:用特定数量的键值对或范围内的键值对替换映射容器的内容。
- `swap`:交换两个映射容器的内容。
3. **迭代器相关**
- `begin`:返回指向第一个键值对的迭代器。
- `end`:返回指向最后一个键值对之后的位置的迭代器。
4. **容量**
- `empty`:判断映射容器是否为空。
- `size`:返回映射容器中键值对的数量。
- `max_size`:返回映射容器最大可容纳的键值对数量。
5. **插入和访问元素**
- `insert`:插入一个键值对或多个键值对。
- `erase`:移除指定键或范围内的键值对。
- `clear`:移除映射容器的所有键值对。
- `find`:查找指定键的迭代器。
- `operator[]`:访问映射容器中指定键对应的值。
6. **其他操作**
- `count`:返回指定键在映射容器中出现的次数。
- `lower_bound`:返回第一个不小于指定键的迭代器。
- `upper_bound`:返回第一个大于指定键的迭代器。
```cpp
#include <iostream>
#include <map>
using namespace std;
int main() {
// 创建空映射容器
map<int, string> mymap;
// 插入键值对
mymap.insert(pair<int, string>(1, "One"));
mymap.insert(make_pair(2, "Two"));
mymap[3] = "Three";
// 访问元素
cout << "Value at key 2: " << mymap[2] << endl;
// 查找元素
map<int, string>::iterator it = mymap.find(3);
if (it != mymap.end()) {
cout << "Key 3 found, value: " << it->second << endl;
}
// 移除键值对
mymap.erase(2);
// 输出键值对数量
cout << "Size of map: " << mymap.size() << endl;
// 遍历输出所有键值对
for (auto& pair : mymap) {
cout << "Key: " << pair.first << ", Value: " << pair.second << endl;
}
return 0;
}
```

View File

@ -0,0 +1,71 @@
1. **构造函数**
- `set()`:创建一个空集合。
- `set(const set& other)`:拷贝构造函数,用另一个集合初始化当前集合。
2. **赋值和交换**
- `operator=`:将一个集合赋值给另一个集合。
- `assign`:用特定数量的元素或范围内的元素替换集合的内容。
- `swap`:交换两个集合的内容。
3. **迭代器相关**
- `begin`:返回指向第一个元素的迭代器。
- `end`:返回指向最后一个元素之后的位置的迭代器。
- `rbegin`:返回指向最后一个元素的反向迭代器。
- `rend`:返回指向第一个元素之前的位置的反向迭代器。
4. **容量**
- `empty`:判断集合是否为空。
- `size`:返回集合中元素的数量。
- `max_size`:返回集合最大可容纳的元素数量。
5. **插入和访问元素**
- `insert`:插入一个元素或多个元素。
- `erase`:移除指定元素或范围内的元素。
- `clear`:移除集合的所有元素。
- `find`:查找指定元素的迭代器。
- `count`:统计指定元素在集合中出现的次数。
6. **其他操作**
- `lower_bound`:返回第一个不小于指定元素的迭代器。
- `upper_bound`:返回第一个大于指定元素的迭代器。
- `equal_range`:返回范围内与指定元素相等的上下界迭代器对。
下面是这些函数的示例用法:
```cpp
#include <iostream>
#include <set>
using namespace std;
int main() {
// 创建空集合
set<int> myset;
// 插入元素
myset.insert(5);
myset.insert(10);
myset.insert(3);
// 查找元素
auto it = myset.find(10);
if (it != myset.end()) {
cout << "Element found: " << *it << endl;
}
// 统计元素个数
int num = myset.count(5);
cout << "Number of 5s: " << num << endl;
// 移除元素
myset.erase(3);
// 输出元素
for (auto& num : myset) {
cout << num << " ";
}
cout << endl;
return 0;
}
```

38
notebook/docs/C++/总.md Normal file
View File

@ -0,0 +1,38 @@
## 万能头
`#include <bits/stdc++.h>` 这个头文件实际上是一个非标准的头文件,在一些编译器中使用它可以简化包含标准库头文件的操作,但并不推荐在生产环境中使用,因为它不是标准的 C++ 头文件。通常情况下,应该直接包含需要的具体标准库头文件,而不是依赖于这个非标准的头文件。
这个头文件通常包含了 C++ 标准库的所有头文件,但具体的内容可能因编译器和系统环境而异。一般来说,它会包含以下头文件:
```cpp
#include <iostream> // 标准输入输出库
#include <fstream> // 文件输入输出库
#include <string> // 字符串处理库
#include <ctime> // 时间处理库
#include <chrono> // 时间处理库C++11
#include <vector> // 向量容器库
#include <list> // 链表容器库
#include <map> // 映射容器库
#include <set> // 集合容器库
#include <algorithm> // 算法库
#include <random> // 随机数库
#include <iomanip> // 控制输出格式库
#include <sstream> // 字符串流库
#include <stdexcept> // 异常处理库
#include <functional> // 函数库
#include <iterator> // 迭代器库
#include <numeric> // 数值算法库
#include <utility> // 实用工具库
#include <tuple> // 元组库
#include <bitset> // 位集合库
#include <array> // 数组库
#include <deque> // 双端队列库
#include <queue> // 队列库
#include <stack> // 栈库
#include <unordered_map> // 无序映射库
#include <unordered_set> // 无序集合库
```
需要注意的是,不同的编译器和环境可能会有不同的实现,因此不能保证所有编译器都支持这种方式,并且不同编译器可能包含的头文件也会有所不同。因此,建议还是根据需要直接包含具体的标准库头文件。

View File

@ -25,7 +25,7 @@ $$
**例如:**
设有矩阵 \( A \) 和 \( B \),如下:
$$
A = \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix}, \quad B = \begin{pmatrix} 5 & 6 \\ 7 & 8 \end{pmatrix}
A = \begin{pmatrix} 1 & 2 \ \ 3 & 4 \end{pmatrix} \quad \( B = \begin{pmatrix} 5 & 6 \ \ 7 & 8 \end{pmatrix}
$$
**乘法:**

View File

@ -1,89 +1,56 @@
进制转换是计算机科学中的一个基本概念。不同的进制表示系统使用不同的基数例如二进制的基数是2十进制的基数是10来表示数字。以下是一些常见的进制及其转换方法
#### **十进制转换成二进制**
### 常见进制
- **二进制Binary**基数为2只使用数字 `0``1`
- **八进制Octal**基数为8使用数字 `0``7`
- **十进制Decimal**基数为10使用数字 `0``9`
- **十六进制Hexadecimal**基数为16使用数字 `0``9` 和字母 `A``F`(或 `a``f`代表10到15
将一个十进制数转换为二进制数的方法是通过**模运算**(求余数)进行的。具体步骤如下:
### 进制转换方法
##### **步骤:**
1. 用十进制数除以2记录余数。
2. 将商继续除以2继续记录余数。
3. 重复此过程直到商为0为止。
4. 将所有余数倒序排列,即为该十进制数对应的二进制表示。
#### 1. 二进制转十进制
将二进制数按权展开,从右到左依次乘以 2 的幂,然后求和。
- 例如,二进制 `1011` 转换为十进制:
\[
1 \times 2^3 + 0 \times 2^2 + 1 \times 2^1 + 1 \times 2^0 = 8 + 0 + 2 + 1 = 11
\]
#### 2. 十进制转二进制
通过不断将十进制数除以2记录每次的余数然后将余数倒序排列得到二进制数。
- 例如,十进制 `13` 转换为二进制:
- 13 ÷ 2 = 6余数 1
- 6 ÷ 2 = 3余数 0
- 3 ÷ 2 = 1余数 1
- 1 ÷ 2 = 0余数 1
- 结果:`1101`
#### 3. 二进制转八进制
将二进制数每三位分组(从右到左),然后将每组转换为对应的八进制数。
- 例如,二进制 `101011` 转换为八进制:
- 将二进制数分组为 `101``011`
- `101` = 5`011` = 3
- 结果:`53`
#### 4. 八进制转二进制
将每个八进制数转换为三位二进制数,拼接得到最终的二进制数。
- 例如,八进制 `53` 转换为二进制:
- `5` = `101``3` = `011`
- 结果:`101011`
#### 5. 十进制转十六进制
通过不断将十进制数除以16记录每次的余数如果余数大于9转换为对应的字母然后将余数倒序排列得到十六进制数。
- 例如,十进制 `255` 转换为十六进制:
- 255 ÷ 16 = 15余数 15对应 `F`
- 15 ÷ 16 = 0余数 15对应 `F`
- 结果:`FF`
#### 6. 十六进制转十进制
将十六进制数按权展开从右到左依次乘以16的幂然后求和。
- 例如,十六进制 `1A3` 转换为十进制:
\[
1 \times 16^2 + 10 \times 16^1 + 3 \times 16^0 = 256 + 160 + 3 = 419
\]
### Python 实现进制转换
Python 提供了一些内置函数来轻松进行进制转换。
- **十进制转其他进制:**
``` python
# 十进制转二进制
print(bin(13)) # 输出0b1101
# 十进制转八进制
print(oct(13)) # 输出0o15
# 十进制转十六进制
print(hex(255)) # 输出0xff
##### **示例:**
将十进制数 `153` 转换为二进制:
```
- **其他进制转十进制:**
``` python
# 二进制转十进制
print(int('1101', 2)) # 输出13
# 八进制转十进制
print(int('15', 8)) # 输出13
# 十六进制转十进制
print(int('ff', 16)) # 输出255
153 ÷ 2 = 76 余 1
76 ÷ 2 = 38 余 0
38 ÷ 2 = 19 余 0
19 ÷ 2 = 9 余 1
9 ÷ 2 = 4 余 1
4 ÷ 2 = 2 余 0
2 ÷ 2 = 1 余 0
1 ÷ 2 = 0 余 1
```
将余数倒序排列,得到 `153` 的二进制表示为:`10011001`
通过理解这些转换方法,可以更好地掌握不同进制之间的关系和计算方法。
---
#### **二进制转换成十进制**
将二进制数转换为十进制数的方法是通过将每一位的数值乘以2的幂次方然后求和。具体步骤如下
##### **步骤:**
1. 从二进制数的最低位开始每一位数乘以2的对应幂次方从0开始计数
2. 将所有结果相加,得到的即是对应的十进制数。
##### **示例:**
将二进制数 `1001101` 转换为十进制:
```
1 * 2^6 = 64
0 * 2^5 = 0
0 * 2^4 = 0
1 * 2^3 = 8
1 * 2^2 = 4
0 * 2^1 = 0
1 * 2^0 = 1
```
求和得到:`64 + 8 + 4 + 1 = 77`
因此,二进制数 `1001101` 对应的十进制数为:`77`
---
#### **总结**
- **十进制转二进制**通过不断除以2并记录余数最终将余数倒序排列。
- **二进制转十进制**通过每一位乘以对应的2的幂次方并将结果相加。
在计算机科学中,理解进制转换是非常重要的,因为不同进制在不同场景下有着广泛的应用。通过这些转换方法,能够轻松在不同进制之间切换,理解数字在不同进制下的表示方式,虽然表示不同,但数学意义是相同的。

View File

@ -0,0 +1,192 @@
### 二叉树
二叉树是一种基础的数据结构,因其简单性和应用的广泛性,深入理解二叉树是掌握许多高级数据结构和算法的基础。以下是对二叉树及其相关知识的更深入讲解。
#### 1. 二叉树的基本性质
- **节点的度Degree of a Node**: 节点的度是该节点的子节点数。在二叉树中每个节点的度最多为2。
- **树的深度Depth of a Tree**: 树的深度是指从树的根节点到最深叶子节点的最长路径上边的数量。
- **层次Level**: 树中某个节点的层次由根节点开始计算根节点的层次为1其子节点的层次为2以此类推。
- **叶子节点Leaf Node**: 叶子节点是没有子节点的节点。在许多算法中,叶子节点的处理通常是终止条件之一。
- **满二叉树Full Binary Tree**: 所有节点的度要么是0叶子节点要么是2。
- **完全二叉树Complete Binary Tree**: 完全二叉树是一种特殊的二叉树,其中每一层除了最后一层之外都是满的,并且最后一层的所有节点尽可能地集中在最左边。
```markdown
完全二叉树的示例:
```
```plaintext
1
/ \
2 3
/ \ /
4 5 6
```
#### 2. 二叉树的表示方式
- **链式表示Linked Representation**: 每个节点包含数据元素和指向其左、右子节点的指针。它非常灵活,可以处理动态增长的树。
```cpp
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
```
- **顺序表示Sequential Representation**: 使用数组存储二叉树节点。对于节点在数组中的位置`i`,其左子节点在位置`2*i + 1`,右子节点在位置`2*i + 2`。
```markdown
顺序表示的示例:
```
```plaintext
1
/ \
2 3
/ \ \
4 5 6
数组表示:[1, 2, 3, 4, 5, null, 6]
```
#### 3. 二叉树的遍历
遍历是指按照某种顺序访问二叉树的所有节点。遍历方式分为深度优先遍历DFS和广度优先遍历BFS
- **深度优先遍历DFS**: 包括前序、中序、后序遍历,它们的区别在于根节点的访问顺序。
- **前序遍历Preorder Traversal**: 根 → 左子树 → 右子树。
- **中序遍历Inorder Traversal**: 左子树 → 根 → 右子树。
- **后序遍历Postorder Traversal**: 左子树 → 右子树 → 根。
- **广度优先遍历BFS**: 层序遍历是一种广度优先遍历方法,它逐层访问树的节点。
```markdown
树的层序遍历:
```
```plaintext
1
/ \
2 3
/ \ \
4 5 6
层序遍历顺序:[1, 2, 3, 4, 5, 6]
```
#### 4. 二叉搜索树BST
二叉搜索树Binary Search Tree是一种特殊的二叉树它具有以下性质
- 对于每个节点,左子树中所有节点的值小于该节点的值,而右子树中所有节点的值大于该节点的值。
- 中序遍历BST会得到一个递增的有序序列。
##### 二叉搜索树的基本操作
1. **查找Search**: 从根节点开始,如果目标值小于当前节点值,进入左子树;如果目标值大于当前节点值,进入右子树;如果目标值等于当前节点值,则查找成功。
2. **插入Insert**: 从根节点开始,根据值的大小决定插入位置。插入的新节点始终是叶子节点。
```cpp
TreeNode* insert(TreeNode* root, int val) {
if (!root) return new TreeNode(val);
if (val < root->val)
root->left = insert(root->left, val);
else
root->right = insert(root->right, val);
return root;
}
```
3. **删除Delete**: 删除节点后需要调整树的结构以保持BST的性质。删除节点有三种情况
- 叶子节点:直接删除。
- 有一个子节点:用该子节点代替删除的节点。
- 有两个子节点:找到右子树中的最小节点,替换要删除的节点,然后删除该最小节点。
```cpp
TreeNode* deleteNode(TreeNode* root, int val) {
if (!root) return nullptr;
if (val < root->val)
root->left = deleteNode(root->left, val);
else if (val > root->val)
root->right = deleteNode(root->right, val);
else {
if (!root->left) return root->right;
if (!root->right) return root->left;
TreeNode* minNode = findMin(root->right);
root->val = minNode->val;
root->right = deleteNode(root->right, minNode->val);
}
return root;
}
TreeNode* findMin(TreeNode* root) {
while (root->left) root = root->left;
return root;
}
```
#### 5. 平衡二叉树Balanced Binary Tree
平衡二叉树是一种特殊的二叉搜索树左右子树的高度差不超过1。常见的平衡二叉树包括以下几种
- **AVL树**: 通过旋转操作来保持平衡的二叉搜索树。插入和删除操作后AVL树会进行调整使得任意节点的左右子树高度差不超过1。
- **红黑树**: 一种自平衡二叉搜索树,具有五条性质:
1. 节点是红色或黑色。
2. 根节点是黑色。
3. 所有叶子节点(`null`节点)是黑色。
4. 如果一个节点是红色,那么它的两个子节点都是黑色(即不能有两个连续的红色节点)。
5. 从任一节点到其每个叶子的所有路径包含相同数目的黑色节点。
#### 6. 二叉树的高级应用
- **表达式树Expression Tree**: 使用二叉树表示算术表达式。叶子节点表示操作数,内部节点表示操作符。可以通过树的遍历顺序来实现表达式的前缀、中缀和后缀表示。
```markdown
表达式:((a + b) * (c - d)) 可以表示为:
```
```plaintext
*
/ \
+ -
/ \ / \
a b c d
```
- **霍夫曼树Huffman Tree**: 霍夫曼树是一种用于数据压缩的二叉树。它是一棵加权路径长度最短的二叉树,通常用于霍夫曼编码。
- **二叉堆Binary Heap**: 一种完全二叉树通常用来实现优先队列。最常见的是最大堆Max Heap和最小堆Min Heap其中最大堆的每个节点都大于等于其子节点最小堆则相反。
#### 7. 二叉树的存储与实现
二叉树可以通过链式存储和顺序存储来实现。链式存储适用于一般的二叉树和动态数据结构,顺序存储则更适合完全二叉树。
##### 链式存储实现
```cpp
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
```
##### 顺序存储实现
```cpp
// 顺序存储的数组表示
vector<int> binaryTree = {1, 2, 3, 4, 5, 6, 7};
```

View File

@ -0,0 +1,163 @@
霍夫曼编码Huffman Coding是一种广泛使用的数据压缩算法特别适用于无损数据压缩。它由David A. Huffman在1952年提出基于信息论中的熵编码思想。
## 霍夫曼编码的基本原理
霍夫曼编码是一种**前缀编码**,即没有任何一个编码是其他编码的前缀。它通过构建一个**最优二叉树**,使得频率越高的字符编码越短,从而减少整体编码的长度,实现数据压缩。
### 主要步骤
1. **统计字符频率**:计算待压缩数据中每个字符出现的频率。
2. **构建优先队列**:将每个字符和其对应的频率作为一个节点,放入优先队列(最小堆)。
3. **构建霍夫曼树**
- 从优先队列中取出两个频率最小的节点,作为左右子节点,构造一个新的父节点,父节点的频率为左右子节点频率之和。
- 将这个新的父节点插回优先队列中。
- 重复上述过程,直到队列中只剩下一个节点,这个节点就是霍夫曼树的根节点。
4. **生成编码**
- 从霍夫曼树的根节点出发,给左边的分支标记为`0`,右边的分支标记为`1`。
- 从根节点到每个叶子节点(即字符节点)路径上的`0`和`1`组合,构成该字符的霍夫曼编码。
### 示例
假设我们有如下字符及其出现频率:
```
字符 | 频率
---------------
A | 5
B | 9
C | 12
D | 13
E | 16
F | 45
```
#### 1. 统计频率
初始优先队列:
```
(A, 5), (B, 9), (C, 12), (D, 13), (E, 16), (F, 45)
```
#### 2. 构建霍夫曼树
- 取出频率最小的两个节点 `(A, 5)``(B, 9)`,构造一个新节点 `(AB, 14)`,插回队列。
- 队列更新为:`(AB, 14), (C, 12), (D, 13), (E, 16), (F, 45)`
- 取出 `(C, 12)``(D, 13)`,构造 `(CD, 25)`,插回队列。
- 队列更新为:`(AB, 14), (CD, 25), (E, 16), (F, 45)`
- 取出 `(AB, 14)``(E, 16)`,构造 `(ABE, 30)`,插回队列。
- 队列更新为:`(CD, 25), (ABE, 30), (F, 45)`
- 取出 `(CD, 25)``(ABE, 30)`,构造 `(CDEAB, 55)`,插回队列。
- 队列更新为:`(CDEAB, 55), (F, 45)`
- 最后将 `(CDEAB, 55)``(F, 45)` 合并为根节点 `(Root, 100)`
最终霍夫曼树:
```
[Root, 100]
/ \
[F, 45] [CDEAB, 55]
/ \
[CD, 25] [ABE, 30]
/ \ / \
[C,12][D,13][A,5] [B,9] [E,16]
```
#### 3. 生成编码
从根节点到每个字符的路径生成编码:
```
F: 0
C: 100
D: 101
A: 1100
B: 1101
E: 111
```
### 霍夫曼编码的优点
- **无损压缩**:霍夫曼编码不会丢失任何信息,解码后的数据与原始数据完全一致。
- **高效性**:对于频率分布差异较大的字符集,霍夫曼编码能显著减少编码后的数据量。
- **简单实现**:算法简单,适合软件实现。
### 霍夫曼编码的应用
- **文件压缩**如ZIP和RAR等文件压缩格式。
- **图像压缩**如JPEG图像格式的压缩。
- **数据传输**:在数据传输中减少带宽占用。
### 示例代码 (C++)
以下是一个简单的C++实现霍夫曼编码的示例:
```cpp
#include <iostream>
#include <vector>
#include <queue>
#include <unordered_map>
using namespace std;
// 定义霍夫曼树节点
struct HuffmanNode {
char data;
int freq;
HuffmanNode *left, *right;
HuffmanNode(char data, int freq) : data(data), freq(freq), left(NULL), right(NULL) {}
};
// 比较器,用于优先队列
struct compare {
bool operator()(HuffmanNode* l, HuffmanNode* r) {
return l->freq > r->freq;
}
};
// 打印霍夫曼编码
void printCodes(HuffmanNode* root, string str) {
if (!root) return;
if (root->data != '$') cout << root->data << ": " << str << "\n";
printCodes(root->left, str + "0");
printCodes(root->right, str + "1");
}
// 构建霍夫曼树并打印编码
void HuffmanCodes(char data[], int freq[], int size) {
HuffmanNode *left, *right, *top;
priority_queue<HuffmanNode*, vector<HuffmanNode*>, compare> minHeap;
for (int i = 0; i < size; ++i)
minHeap.push(new HuffmanNode(data[i], freq[i]));
while (minHeap.size() != 1) {
left = minHeap.top();
minHeap.pop();
right = minHeap.top();
minHeap.pop();
top = new HuffmanNode('$', left->freq + right->freq);
top->left = left;
top->right = right;
minHeap.push(top);
}
printCodes(minHeap.top(), "");
}
int main() {
char arr[] = { 'A', 'B', 'C', 'D', 'E', 'F' };
int freq[] = { 5, 9, 12, 13, 16, 45 };
int size = sizeof(arr) / sizeof(arr[0]);
HuffmanCodes(arr, freq, size);
return 0;
}
```
### 总结
霍夫曼编码是非常有效的无损压缩算法,特别适用于字符频率分布不均的情况。它的思想简单但非常实用,在许多领域得到了广泛应用。

View File

@ -16,6 +16,22 @@ nav:
- 数学基础:
- 进制转换: basic/math/进制转换.md
- 矩阵运算: basic/math/矩阵运算.md
- C++库:
- 总结: C++/总.md
- iostream: C++/1.iostream.md
- fstream: C++/2.fstream.md
- sring: C++/3.string.md
- ctime: C++/4.ctime.md
- chrono: C++/5.chrono.md
- vector: C++/6.vector.md
- list: C++/7.list.md
- map: C++/8.map.md
- set: C++/9.set.md
- algorithm: C++/10.algorithm.md
- 数据结构:
- 二叉树:
- 二叉树: data_structure/二叉树.md
- 霍夫曼编码: data_structure/霍夫曼编码.md
- 电子学会考级(机器人):
- 历史人物: 电子学会考级/历史事件及人物.md
- 泰拉瑞亚: