├── Armadillo线性回归模型 ├── CMakeLists.txt ├── README.md ├── include │ ├── core │ │ ├── adaptive_tree.hpp │ │ ├── distributed_forest.hpp │ │ └── tree_node.hpp │ └── utils │ │ ├── data_loader.hpp │ │ └── metrics.hpp └── src │ ├── core │ ├── adaptive_tree.cpp │ ├── distributed_forest.cpp │ └── tree_node.cpp │ ├── main.cpp │ ├── predict.cpp │ └── utils │ ├── data_loader.cpp │ ├── data_loader.hpp │ ├── data_loader_static.cpp │ └── metrics.cpp ├── C++实现GNN ├── README.md ├── gnn └── gnn.cpp ├── C++实现一个基于ID3:C4.5算法的决策树分类器 ├── CMakeLists.txt ├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.26.4 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ ├── CompilerIdC │ │ │ │ ├── CMakeCCompilerId.c │ │ │ │ └── CMakeCCompilerId.o │ │ │ └── CompilerIdCXX │ │ │ │ ├── CMakeCXXCompilerId.cpp │ │ │ │ └── CMakeCXXCompilerId.o │ │ ├── CMakeConfigureLog.yaml │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── Makefile.cmake │ │ ├── Makefile2 │ │ ├── TargetDirectories.txt │ │ ├── cmake.check_cache │ │ ├── decision_tree.dir │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── compiler_depend.make │ │ │ ├── compiler_depend.ts │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ ├── progress.make │ │ │ └── src │ │ │ │ ├── DecisionTree.cpp.o │ │ │ │ ├── DecisionTree.cpp.o.d │ │ │ │ ├── main.cpp.o │ │ │ │ └── main.cpp.o.d │ │ └── progress.marks │ ├── Makefile │ ├── cmake_install.cmake │ ├── decision_tree │ ├── decision_tree.dot │ └── iris.csv ├── decision_tree.png ├── iris.csv └── src │ ├── DecisionTree.cpp │ ├── DecisionTree.h │ ├── Node.h │ └── main.cpp ├── C++实现手写数字识别.zip ├── C++实现股票价格预测系统 ├── CMakeLists.txt ├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.31.5 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ ├── CompilerIdC │ │ │ │ ├── CMakeCCompilerId.c │ │ │ │ └── CMakeCCompilerId.o │ │ │ └── CompilerIdCXX │ │ │ │ ├── CMakeCXXCompilerId.cpp │ │ │ │ └── CMakeCXXCompilerId.o │ │ ├── CMakeConfigureLog.yaml │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── Makefile.cmake │ │ ├── Makefile2 │ │ ├── StockPricePredictor.dir │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── compiler_depend.internal │ │ │ ├── compiler_depend.make │ │ │ ├── compiler_depend.ts │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ ├── progress.make │ │ │ └── src │ │ │ │ ├── arima_model.cpp.o │ │ │ │ ├── arima_model.cpp.o.d │ │ │ │ ├── data_processor.cpp.o │ │ │ │ ├── data_processor.cpp.o.d │ │ │ │ ├── main.cpp.o │ │ │ │ └── main.cpp.o.d │ │ ├── TargetDirectories.txt │ │ ├── cmake.check_cache │ │ └── progress.marks │ ├── Makefile │ ├── StockPricePredictor │ ├── cmake_install.cmake │ └── sample_data.csv ├── include │ ├── arima_model.hpp │ └── data_processor.hpp └── src │ ├── arima_model.cpp │ ├── data_processor.cpp │ ├── data_processor.hpp │ └── main.cpp ├── C++面试急救包:20道必考算法题答案 ├── C++面试急救包:20道必考算法题答案.md ├── m1.png ├── m2.png └── m3.png ├── C语言实现简单Linux容器 ├── README.md ├── container └── simple_container.c ├── C语言编写哈希表 └── hash_table.c ├── Hsmm-HTTP-Server ├── CMakeLists.txt ├── README.md ├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.31.6 │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ └── CompilerIdCXX │ │ │ │ ├── CMakeCXXCompilerId.cpp │ │ │ │ └── CMakeCXXCompilerId.o │ │ ├── CMakeConfigureLog.yaml │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── Makefile.cmake │ │ ├── Makefile2 │ │ ├── TargetDirectories.txt │ │ ├── cmake.check_cache │ │ ├── hsmmserver.dir │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── compiler_depend.internal │ │ │ ├── compiler_depend.make │ │ │ ├── compiler_depend.ts │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ ├── progress.make │ │ │ └── src │ │ │ │ ├── http │ │ │ │ ├── HttpParser.cpp.o │ │ │ │ └── HttpParser.cpp.o.d │ │ │ │ ├── main.cpp.o │ │ │ │ ├── main.cpp.o.d │ │ │ │ └── server │ │ │ │ ├── Connection.cpp.o │ │ │ │ ├── Connection.cpp.o.d │ │ │ │ ├── Server.cpp.o │ │ │ │ └── Server.cpp.o.d │ │ ├── progress.marks │ │ └── stress_test.dir │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── compiler_depend.internal │ │ │ ├── compiler_depend.make │ │ │ ├── compiler_depend.ts │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ ├── progress.make │ │ │ └── src │ │ │ └── test │ │ │ ├── stress_test.cpp.o │ │ │ └── stress_test.cpp.o.d │ ├── Makefile │ ├── bin │ │ ├── hsmmserver │ │ └── stress_test │ ├── cmake_install.cmake │ └── logs │ │ └── server.log ├── include │ ├── http │ │ └── HttpParser.hpp │ ├── server │ │ ├── Connection.hpp │ │ └── Server.hpp │ └── utils │ │ ├── Logger.hpp │ │ └── SafeBuffer.hpp └── src │ ├── http │ └── HttpParser.cpp │ ├── main.cpp │ ├── server │ ├── Connection.cpp │ └── Server.cpp │ └── test │ └── stress_test.cpp ├── README.md ├── c-shell └── main.c ├── memalloc ├── README.md └── memalloc.c ├── movie_recommender ├── CMakeLists.txt ├── Database.cpp ├── Database.h ├── MovieRecommender.cpp ├── MovieRecommender.h ├── SVD.cpp ├── SVD.h ├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.31.5 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeCXXCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeDetermineCompilerABI_CXX.bin │ │ │ ├── CMakeSystem.cmake │ │ │ ├── CompilerIdC │ │ │ │ ├── CMakeCCompilerId.c │ │ │ │ └── CMakeCCompilerId.o │ │ │ └── CompilerIdCXX │ │ │ │ ├── CMakeCXXCompilerId.cpp │ │ │ │ └── CMakeCXXCompilerId.o │ │ ├── CMakeConfigureLog.yaml │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── Makefile.cmake │ │ ├── Makefile2 │ │ ├── TargetDirectories.txt │ │ ├── cmake.check_cache │ │ ├── movie_recommender.dir │ │ │ ├── Database.cpp.o │ │ │ ├── Database.cpp.o.d │ │ │ ├── DependInfo.cmake │ │ │ ├── MovieRecommender.cpp.o │ │ │ ├── MovieRecommender.cpp.o.d │ │ │ ├── SVD.cpp.o │ │ │ ├── SVD.cpp.o.d │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── compiler_depend.internal │ │ │ ├── compiler_depend.make │ │ │ ├── compiler_depend.ts │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ ├── main.cpp.o │ │ │ ├── main.cpp.o.d │ │ │ └── progress.make │ │ └── progress.marks │ ├── Makefile │ ├── cmake_install.cmake │ ├── movie_recommender │ └── movies.db └── main.cpp ├── 使用C:C++构建自己的redis ├── 10 │ ├── avl.cpp │ ├── avl.h │ └── test_avl.cpp ├── 11 │ ├── 11_server.cpp │ ├── avl.cpp │ ├── avl.h │ ├── common.h │ ├── hashtable.cpp │ ├── hashtable.h │ ├── test_cmds.py │ ├── test_offset.cpp │ ├── zset.cpp │ └── zset.h ├── 12 │ ├── 12_server.cpp │ ├── avl.cpp │ ├── avl.h │ ├── common.h │ ├── hashtable.cpp │ ├── hashtable.h │ ├── list.h │ ├── zset.cpp │ └── zset.h ├── 13 │ ├── 13_server.cpp │ ├── avl.cpp │ ├── avl.h │ ├── common.h │ ├── hashtable.cpp │ ├── hashtable.h │ ├── heap.cpp │ ├── heap.h │ ├── list.h │ ├── test_heap.cpp │ ├── zset.cpp │ └── zset.h ├── 14 │ ├── 14_server.cpp │ ├── avl.cpp │ ├── avl.h │ ├── common.h │ ├── hashtable.cpp │ ├── hashtable.h │ ├── heap.cpp │ ├── heap.h │ ├── list.h │ ├── thread_pool.cpp │ ├── thread_pool.h │ ├── zset.cpp │ └── zset.h ├── 03 │ ├── 03_client.cpp │ └── 03_server.cpp ├── 04 │ ├── 04_client.cpp │ └── 04_server.cpp ├── 06 │ ├── 06_client.cpp │ └── 06_server.cpp ├── 07 │ ├── 07_client.cpp │ └── 07_server.cpp ├── 08 │ ├── 08_server.cpp │ ├── hashtable.cpp │ └── hashtable.h └── 09 │ ├── 09_client.cpp │ ├── 09_server.cpp │ ├── hashtable.cpp │ └── hashtable.h └── 超高并发场景优化的定制化C++ STL 库 └── HighConcurrencySTL ├── CMakeLists.txt ├── LICENSE ├── README.md ├── benchmarks ├── CMakeLists.txt └── container_benchmarks.cpp ├── cmake └── hcstl-config.cmake.in ├── examples ├── CMakeLists.txt └── container_example.cpp ├── include └── hcstl │ ├── concurrent_map.hpp │ ├── concurrent_queue.hpp │ └── concurrent_vector.hpp └── tests ├── CMakeLists.txt └── container_tests.cpp /Armadillo线性回归模型/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(advanced_random_forest CXX) 3 | 4 | # 设置C++标准 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | # 设置编译选项 9 | if(NOT CMAKE_BUILD_TYPE) 10 | set(CMAKE_BUILD_TYPE Release) 11 | endif() 12 | 13 | # 设置编译优化 14 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") 15 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") 16 | 17 | # 设置MPI编译器 18 | set(MPI_CXX_COMPILER "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/installed/x64-osx/tools/openmpi/bin/mpicxx") 19 | set(MPI_C_COMPILER "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/installed/x64-osx/tools/openmpi/bin/mpicc") 20 | 21 | # 设置OpenMP配置 22 | if(APPLE) 23 | if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") 24 | set(OpenMP_CXX "${CMAKE_CXX_COMPILER}") 25 | set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp -I/usr/local/Homebrew/Cellar/libomp/20.1.0/include") 26 | set(OpenMP_CXX_LIB_NAMES "omp") 27 | set(OpenMP_omp_LIBRARY "/usr/local/Homebrew/Cellar/libomp/20.1.0/lib/libomp.dylib") 28 | endif() 29 | endif() 30 | 31 | # 设置vcpkg工具链 32 | set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake" 33 | CACHE STRING "Vcpkg toolchain file") 34 | 35 | # 设置Armadillo路径 36 | set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/installed/x64-osx") 37 | 38 | # 查找依赖包 39 | find_package(Armadillo REQUIRED) 40 | find_package(OpenMP REQUIRED) 41 | find_package(MPI REQUIRED) 42 | find_package(CURL REQUIRED) 43 | 44 | # 添加头文件路径 45 | include_directories(${CMAKE_SOURCE_DIR}/include) 46 | include_directories(${ARMADILLO_INCLUDE_DIRS}) 47 | include_directories(${MPI_INCLUDE_PATH}) 48 | include_directories(${CURL_INCLUDE_DIRS}) 49 | 50 | # 添加源文件 51 | set(SOURCES 52 | src/core/adaptive_tree.cpp 53 | src/core/distributed_forest.cpp 54 | src/core/tree_node.cpp 55 | src/utils/data_loader.cpp 56 | src/utils/data_loader_static.cpp 57 | src/utils/metrics.cpp 58 | ) 59 | 60 | # 创建训练可执行文件 61 | add_executable(random_forest ${SOURCES} src/main.cpp) 62 | 63 | # 创建预测可执行文件 64 | add_executable(predict ${SOURCES} src/predict.cpp) 65 | 66 | # 链接库 67 | foreach(target random_forest predict) 68 | target_link_libraries(${target} 69 | PRIVATE 70 | ${ARMADILLO_LIBRARIES} 71 | OpenMP::OpenMP_CXX 72 | MPI::MPI_CXX 73 | CURL::libcurl 74 | ) 75 | 76 | # 设置编译选项 77 | target_compile_options(${target} 78 | PRIVATE 79 | -Wall 80 | -Wextra 81 | -O3 82 | ) 83 | endforeach() 84 | 85 | # 如果是macOS,添加OpenMP库路径 86 | if(APPLE) 87 | foreach(target random_forest predict) 88 | target_link_directories(${target} PRIVATE /usr/local/Homebrew/Cellar/libomp/20.1.0/lib) 89 | target_link_libraries(${target} PRIVATE omp) 90 | endforeach() 91 | endif() -------------------------------------------------------------------------------- /Armadillo线性回归模型/include/core/adaptive_tree.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "tree_node.hpp" 4 | #include 5 | #include 6 | 7 | namespace rf { 8 | 9 | /** 10 | * @brief 自适应决策树类 11 | * 12 | * 实现了动态深度的CART回归树,支持在线学习和自适应特征选择 13 | */ 14 | class AdaptiveTree { 15 | public: 16 | /** 17 | * @brief 构造函数 18 | * @param max_depth 最大树深度 19 | * @param min_samples_split 最小分裂样本数 20 | * @param lambda 复杂度惩罚系数 21 | */ 22 | AdaptiveTree(size_t max_depth = 10, 23 | size_t min_samples_split = 2, 24 | double lambda = 0.1); 25 | 26 | /** 27 | * @brief 训练模型 28 | * @param X 训练数据 29 | * @param y 目标值 30 | * @param feature_subset_size 特征子集大小 31 | */ 32 | void fit(const arma::mat& X, const arma::vec& y, size_t feature_subset_size = 0); 33 | 34 | /** 35 | * @brief 预测 36 | * @param X 测试数据 37 | * @return 预测值 38 | */ 39 | arma::vec predict(const arma::mat& X) const; 40 | 41 | /** 42 | * @brief 在线更新模型 43 | * @param X_new 新数据 44 | * @param y_new 新数据的目标值 45 | */ 46 | void update(const arma::mat& X_new, const arma::vec& y_new); 47 | 48 | /** 49 | * @brief 获取特征重要性 50 | * @return 特征重要性向量 51 | */ 52 | arma::vec get_feature_importance() const; 53 | 54 | /** 55 | * @brief 获取根节点 56 | * @return 根节点指针 57 | */ 58 | TreeNode::NodePtr get_root() const { return root_; } 59 | 60 | /** 61 | * @brief 设置根节点 62 | * @param node 根节点指针 63 | */ 64 | void set_root(const TreeNode::NodePtr& node) { root_ = node; } 65 | 66 | private: 67 | size_t max_depth_; ///< 最大树深度 68 | size_t min_samples_split_; ///< 最小分裂样本数 69 | double lambda_; ///< 复杂度惩罚系数 70 | std::mt19937 rng_; ///< 随机数生成器 71 | TreeNode::NodePtr root_; ///< 根节点 72 | std::vector feature_importance_; ///< 特征重要性 73 | 74 | /** 75 | * @brief 构建决策树 76 | * @param X 训练数据 77 | * @param y 目标值 78 | * @param depth 当前深度 79 | * @param available_features 可用特征索引 80 | * @return 树节点指针 81 | */ 82 | TreeNode::NodePtr build_tree(const arma::mat& X, 83 | const arma::vec& y, 84 | size_t depth, 85 | const std::vector& available_features); 86 | 87 | /** 88 | * @brief 寻找最佳分割点 89 | * @param X 训练数据 90 | * @param y 目标值 91 | * @param available_features 可用特征索引 92 | * @return {最佳特征索引, 最佳阈值} 93 | */ 94 | std::pair find_best_split(const arma::mat& X, 95 | const arma::vec& y, 96 | const std::vector& available_features); 97 | 98 | /** 99 | * @brief 计算分割增益 100 | * @param y_left 左子节点目标值 101 | * @param y_right 右子节点目标值 102 | * @return 分割增益 103 | */ 104 | double calculate_split_gain(const arma::vec& y_left, const arma::vec& y_right) const; 105 | 106 | /** 107 | * @brief 检查是否应该剪枝 108 | * @param node 当前节点 109 | * @param X 验证数据 110 | * @param y 验证数据目标值 111 | * @return 是否应该剪枝 112 | */ 113 | bool should_prune(const TreeNode::NodePtr& node, 114 | const arma::mat& X, 115 | const arma::vec& y) const; 116 | }; 117 | 118 | } // namespace rf -------------------------------------------------------------------------------- /Armadillo线性回归模型/include/core/distributed_forest.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "adaptive_tree.hpp" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace rf { 10 | 11 | /** 12 | * @brief 分布式随机森林类 13 | * 14 | * 实现了基于MPI的分布式随机森林,支持多机训练和预测 15 | */ 16 | class DistributedForest { 17 | public: 18 | /** 19 | * @brief 构造函数 20 | * @param n_trees_total 总树的数量 21 | * @param max_depth 最大树深度 22 | * @param min_samples_split 最小分裂样本数 23 | * @param feature_ratio 特征采样比例 24 | * @param lambda 复杂度惩罚系数 25 | */ 26 | DistributedForest(size_t n_trees_total = 100, 27 | size_t max_depth = 10, 28 | size_t min_samples_split = 2, 29 | double feature_ratio = 0.7, 30 | double lambda = 0.1); 31 | 32 | /** 33 | * @brief 析构函数 34 | */ 35 | ~DistributedForest(); 36 | 37 | /** 38 | * @brief 训练模型 39 | * @param X 特征矩阵 40 | * @param y 目标值向量 41 | */ 42 | void fit(const arma::mat& X, const arma::vec& y); 43 | 44 | /** 45 | * @brief 预测新样本 46 | * @param X 特征矩阵 47 | * @return 预测值向量 48 | */ 49 | arma::vec predict(const arma::mat& X) const; 50 | 51 | /** 52 | * @brief 在线更新模型 53 | * @param X_new 新特征矩阵 54 | * @param y_new 新目标值向量 55 | */ 56 | void update(const arma::mat& X_new, const arma::vec& y_new); 57 | 58 | /** 59 | * @brief 获取特征重要性分数 60 | * @return 特征重要性向量 61 | */ 62 | arma::vec get_feature_importance() const; 63 | 64 | /** 65 | * @brief 检查是否为主进程 66 | * @return 是否为主进程 67 | */ 68 | bool is_master() const { return is_master_; } 69 | 70 | /** 71 | * @brief 保存模型到文件 72 | * @param filename 文件名 73 | */ 74 | void save_model(const std::string& filename) const; 75 | 76 | /** 77 | * @brief 从文件加载模型 78 | * @param filename 文件名 79 | */ 80 | void load_model(const std::string& filename); 81 | 82 | private: 83 | /** 84 | * @brief 初始化MPI环境 85 | */ 86 | void init_mpi(); 87 | 88 | /** 89 | * @brief 分发数据到各个进程 90 | * @param X 特征矩阵 91 | * @param y 目标值向量 92 | */ 93 | void distribute_data(const arma::mat& X, const arma::vec& y); 94 | 95 | /** 96 | * @brief 收集所有进程的预测结果 97 | * @param local_preds 本地预测结果 98 | * @return 全局预测结果 99 | */ 100 | arma::vec gather_predictions(const arma::vec& local_preds) const; 101 | 102 | /** 103 | * @brief 同步特征重要性 104 | */ 105 | void sync_feature_importance(); 106 | 107 | /** 108 | * @brief 保存单棵树到文件 109 | * @param file 输出文件流 110 | * @param node 当前节点 111 | */ 112 | void save_tree(std::ofstream& file, const TreeNode::NodePtr& node) const; 113 | 114 | /** 115 | * @brief 从文件加载单棵树 116 | * @param file 输入文件流 117 | * @return 树的根节点 118 | */ 119 | TreeNode::NodePtr load_tree(std::ifstream& file); 120 | 121 | /** 122 | * @brief 广播模型到所有进程 123 | */ 124 | void broadcast_model(); 125 | 126 | private: 127 | int rank_; ///< MPI进程的rank 128 | int world_size_; ///< MPI进程的总数 129 | bool is_master_; ///< 是否是主进程 130 | size_t n_trees_total_; ///< 总树的数量 131 | size_t n_trees_local_; ///< 当前进程的树数量 132 | size_t max_depth_; ///< 树的最大深度 133 | size_t min_samples_split_; ///< 分裂所需的最小样本数 134 | double feature_ratio_; ///< 特征采样比例 135 | double lambda_; ///< 正则化参数 136 | std::vector> trees_; ///< 当前进程的树集合 137 | arma::vec feature_importance_; ///< 全局特征重要性 138 | }; 139 | 140 | } // namespace rf -------------------------------------------------------------------------------- /Armadillo线性回归模型/include/core/tree_node.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rf { 7 | 8 | /** 9 | * @brief 决策树节点类 10 | * 11 | * 实现了自适应决策树的节点结构,支持动态特征选择和在线更新 12 | */ 13 | class TreeNode { 14 | public: 15 | using NodePtr = std::shared_ptr; 16 | 17 | /** 18 | * @brief 节点类型枚举 19 | */ 20 | enum class NodeType { 21 | LEAF, ///< 叶节点 22 | INTERNAL ///< 内部节点 23 | }; 24 | 25 | /** 26 | * @brief 构造叶节点 27 | * @param value 节点预测值 28 | */ 29 | explicit TreeNode(double value); 30 | 31 | /** 32 | * @brief 构造内部节点 33 | * @param feature_idx 分割特征索引 34 | * @param threshold 分割阈值 35 | */ 36 | TreeNode(size_t feature_idx, double threshold); 37 | 38 | /** 39 | * @brief 预测单个样本 40 | * @param x 输入特征向量 41 | * @return 预测值 42 | */ 43 | double predict(const arma::vec& x) const; 44 | 45 | /** 46 | * @brief 更新节点统计信息 47 | * @param x 输入特征向量 48 | * @param y 目标值 49 | */ 50 | void update_stats(const arma::vec& x, double y); 51 | 52 | /** 53 | * @brief 检查是否应该分裂节点 54 | * @param min_samples_split 最小分裂样本数 55 | * @param max_depth 最大深度 56 | * @param current_depth 当前深度 57 | * @return 是否应该分裂 58 | */ 59 | bool should_split(size_t min_samples_split, size_t max_depth, size_t current_depth) const; 60 | 61 | // Getters 62 | NodeType get_type() const { return type_; } 63 | size_t get_feature_idx() const { return feature_idx_; } 64 | double get_threshold() const { return threshold_; } 65 | double get_value() const { return value_; } 66 | const NodePtr& get_left() const { return left_; } 67 | const NodePtr& get_right() const { return right_; } 68 | 69 | // Setters 70 | void set_left(NodePtr left) { left_ = std::move(left); } 71 | void set_right(NodePtr right) { right_ = std::move(right); } 72 | 73 | private: 74 | NodeType type_; ///< 节点类型 75 | size_t feature_idx_; ///< 分割特征索引 76 | double threshold_; ///< 分割阈值 77 | double value_; ///< 叶节点预测值 78 | size_t n_samples_; ///< 样本数量 79 | double sum_; ///< 样本值之和 80 | double sum_squared_; ///< 样本值平方和 81 | NodePtr left_; ///< 左子节点 82 | NodePtr right_; ///< 右子节点 83 | }; 84 | 85 | } // namespace rf -------------------------------------------------------------------------------- /Armadillo线性回归模型/include/utils/data_loader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rf { 7 | 8 | /** 9 | * @brief 数据加载器类 10 | */ 11 | class DataLoader { 12 | public: 13 | /** 14 | * @brief 批次迭代器类 15 | */ 16 | class BatchIterator { 17 | public: 18 | /** 19 | * @brief 构造函数 20 | * @param X 特征矩阵 21 | * @param y 目标值 22 | * @param batch_size 批次大小 23 | */ 24 | BatchIterator(const arma::mat& X, const arma::vec& y, arma::uword batch_size); 25 | 26 | /** 27 | * @brief 检查是否还有下一个批次 28 | * @return 是否有下一个批次 29 | */ 30 | bool has_next() const; 31 | 32 | /** 33 | * @brief 获取下一个批次 34 | * @return 是否成功获取下一个批次 35 | */ 36 | bool next(); 37 | 38 | /** 39 | * @brief 获取当前批次的特征矩阵 40 | * @return 当前批次的特征矩阵 41 | */ 42 | const arma::mat& get_current_batch() const { return current_batch_; } 43 | 44 | /** 45 | * @brief 获取当前批次的标签 46 | * @return 当前批次的标签 47 | */ 48 | const arma::vec& get_current_labels() const { return current_labels_; } 49 | 50 | private: 51 | const arma::mat& X_; ///< 特征矩阵引用 52 | const arma::vec& y_; ///< 目标值引用 53 | arma::uword batch_size_; ///< 批次大小 54 | arma::uword current_pos_; ///< 当前位置 55 | arma::mat current_batch_; ///< 当前批次的特征矩阵 56 | arma::vec current_labels_; ///< 当前批次的标签 57 | }; 58 | 59 | /** 60 | * @brief 构造函数 61 | * @param batch_size 批次大小 62 | */ 63 | explicit DataLoader(arma::uword batch_size = 32); 64 | 65 | /** 66 | * @brief 从CSV文件加载数据 67 | * @param filename 文件名 68 | * @param has_header 是否有表头 69 | * @return pair<特征矩阵, 目标值向量> 70 | */ 71 | std::pair load_csv(const std::string& filename, bool has_header = true); 72 | 73 | /** 74 | * @brief 使用内存映射加载大文件 75 | * @param filename 文件名 76 | * @param has_header 是否有表头 77 | * @return pair<特征矩阵, 目标值向量> 78 | */ 79 | std::pair load_large_csv(const std::string& filename, bool has_header = true); 80 | 81 | /** 82 | * @brief 获取批次迭代器 83 | * @param X 特征矩阵 84 | * @param y 目标值向量 85 | * @return BatchIterator对象 86 | */ 87 | BatchIterator get_batch_iterator(const arma::mat& X, const arma::vec& y); 88 | 89 | /** 90 | * @brief 特征标准化 91 | * @param X 输入特征矩阵 92 | * @return 标准化后的特征矩阵 93 | */ 94 | arma::mat standardize(const arma::mat& X); 95 | 96 | /** 97 | * @brief 特征归一化 98 | * @param X 输入特征矩阵 99 | * @return 归一化后的特征矩阵 100 | */ 101 | arma::mat normalize(const arma::mat& X); 102 | 103 | /** 104 | * @brief 处理缺失值 105 | * @param X 输入特征矩阵 106 | * @param strategy 处理策略("mean", "median", "mode") 107 | * @return 处理后的特征矩阵 108 | */ 109 | arma::mat handle_missing_values(const arma::mat& X, const std::string& strategy = "mean"); 110 | 111 | /** 112 | * @brief 下载加州房价数据集 113 | * @param save_path 保存路径 114 | * @return pair<特征矩阵, 目标值向量> 115 | */ 116 | static std::pair load_california_housing(const std::string& save_path = "data/california_housing.csv"); 117 | 118 | private: 119 | arma::uword batch_size_; ///< 批处理大小 120 | arma::vec mean_; ///< 特征均值 121 | arma::vec std_; ///< 特征标准差 122 | arma::vec min_; ///< 特征最小值 123 | arma::vec max_; ///< 特征最大值 124 | }; 125 | 126 | } // namespace rf -------------------------------------------------------------------------------- /Armadillo线性回归模型/include/utils/metrics.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace rf { 10 | 11 | /** 12 | * @brief 性能评估和监控类 13 | * 14 | * 实现了模型评估、性能监控和资源使用统计功能 15 | */ 16 | class Metrics { 17 | public: 18 | /** 19 | * @brief 回归指标结构体 20 | */ 21 | struct RegressionMetrics { 22 | double mse; ///< 均方误差 23 | double rmse; ///< 均方根误差 24 | double mae; ///< 平均绝对误差 25 | double r2; ///< R²分数 26 | double explained_variance; ///< 解释方差分数 27 | }; 28 | 29 | /** 30 | * @brief 计时器结构体 31 | */ 32 | struct Timer { 33 | std::chrono::high_resolution_clock::time_point start_time; 34 | double total_time = 0.0; 35 | size_t count = 0; 36 | }; 37 | 38 | /** 39 | * @brief 内存使用结构体 40 | */ 41 | struct MemoryUsage { 42 | size_t current_usage = 0; 43 | size_t peak_usage = 0; 44 | std::vector history; 45 | }; 46 | 47 | /** 48 | * @brief 训练进度结构体 49 | */ 50 | struct TrainingProgress { 51 | size_t epoch; 52 | RegressionMetrics metrics; 53 | double time; 54 | }; 55 | 56 | /** 57 | * @brief 构造函数 58 | */ 59 | Metrics(); 60 | 61 | /** 62 | * @brief 计算回归指标 63 | * @param y_true 真实值 64 | * @param y_pred 预测值 65 | * @return 回归指标 66 | */ 67 | static RegressionMetrics calculate_regression_metrics(const arma::vec& y_true, 68 | const arma::vec& y_pred); 69 | 70 | /** 71 | * @brief 开始计时 72 | * @param name 计时器名称 73 | */ 74 | void start_timer(const std::string& name); 75 | 76 | /** 77 | * @brief 停止计时 78 | * @param name 计时器名称 79 | * @return 耗时(毫秒) 80 | */ 81 | double stop_timer(const std::string& name); 82 | 83 | /** 84 | * @brief 记录内存使用 85 | * @param name 记录名称 86 | * @param bytes 使用字节数 87 | */ 88 | void record_memory_usage(const std::string& name, size_t bytes); 89 | 90 | /** 91 | * @brief 记录训练进度 92 | * @param epoch 当前轮次 93 | * @param metrics 性能指标 94 | */ 95 | void record_training_progress(size_t epoch, const RegressionMetrics& metrics); 96 | 97 | /** 98 | * @brief 生成性能报告 99 | * @return 报告字符串 100 | */ 101 | std::string generate_report() const; 102 | 103 | /** 104 | * @brief 导出性能指标 105 | * @param filename 文件名 106 | */ 107 | void export_metrics(const std::string& filename) const; 108 | 109 | private: 110 | std::map timers_; 111 | std::map memory_usage_; 112 | std::vector training_history_; 113 | }; 114 | 115 | } // namespace rf -------------------------------------------------------------------------------- /Armadillo线性回归模型/src/core/tree_node.cpp: -------------------------------------------------------------------------------- 1 | #include "core/tree_node.hpp" 2 | 3 | namespace rf { 4 | 5 | TreeNode::TreeNode(double value) 6 | : type_(NodeType::LEAF) 7 | , feature_idx_(0) 8 | , threshold_(0.0) 9 | , value_(value) 10 | , n_samples_(0) 11 | , sum_(0.0) 12 | , sum_squared_(0.0) {} 13 | 14 | TreeNode::TreeNode(size_t feature_idx, double threshold) 15 | : type_(NodeType::INTERNAL) 16 | , feature_idx_(feature_idx) 17 | , threshold_(threshold) 18 | , value_(0.0) 19 | , n_samples_(0) 20 | , sum_(0.0) 21 | , sum_squared_(0.0) {} 22 | 23 | double TreeNode::predict(const arma::vec& x) const { 24 | if (type_ == NodeType::LEAF) { 25 | return value_; 26 | } 27 | 28 | if (x(feature_idx_) <= threshold_) { 29 | return left_->predict(x); 30 | } else { 31 | return right_->predict(x); 32 | } 33 | } 34 | 35 | void TreeNode::update_stats(const arma::vec& x, double y) { 36 | n_samples_++; 37 | sum_ += y; 38 | sum_squared_ += y * y; 39 | 40 | if (type_ == NodeType::INTERNAL) { 41 | if (x(feature_idx_) <= threshold_) { 42 | left_->update_stats(x, y); 43 | } else { 44 | right_->update_stats(x, y); 45 | } 46 | } else { 47 | // 更新叶节点的预测值为均值 48 | value_ = sum_ / n_samples_; 49 | } 50 | } 51 | 52 | bool TreeNode::should_split(size_t min_samples_split, size_t max_depth, size_t current_depth) const { 53 | // 检查是否满足分裂条件 54 | if (type_ == NodeType::INTERNAL) { 55 | return false; // 已经是内部节点 56 | } 57 | 58 | if (current_depth >= max_depth) { 59 | return false; // 达到最大深度 60 | } 61 | 62 | if (n_samples_ < min_samples_split) { 63 | return false; // 样本数不足 64 | } 65 | 66 | // 计算方差,检查是否值得分裂 67 | double mean = sum_ / n_samples_; 68 | double variance = (sum_squared_ / n_samples_) - (mean * mean); 69 | 70 | return variance > 1e-6; // 方差足够大时分裂 71 | } 72 | 73 | } // namespace rf -------------------------------------------------------------------------------- /Armadillo线性回归模型/src/predict.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "core/distributed_forest.hpp" 5 | #include "utils/data_loader.hpp" 6 | #include "utils/metrics.hpp" 7 | 8 | using namespace rf; 9 | using namespace std; 10 | 11 | int main(int argc, char** argv) { 12 | // 初始化MPI 13 | MPI_Init(&argc, &argv); 14 | 15 | int rank; 16 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); 17 | bool is_master = (rank == 0); 18 | 19 | try { 20 | // 加载数据 21 | arma::mat X; 22 | arma::vec y; 23 | 24 | if (is_master) { 25 | try { 26 | auto data = DataLoader::load_california_housing(); 27 | X = std::move(data.first); 28 | y = std::move(data.second); 29 | 30 | if (X.n_rows == 0) { 31 | throw std::runtime_error("数据集加载失败"); 32 | } 33 | 34 | std::cout << "数据集加载成功!\n"; 35 | std::cout << "样本数量: " << X.n_rows << "\n"; 36 | std::cout << "特征数量: " << X.n_cols << "\n\n"; 37 | } catch (const std::exception& e) { 38 | std::cerr << "数据加载错误:" << e.what() << std::endl; 39 | MPI_Abort(MPI_COMM_WORLD, 1); 40 | return 1; 41 | } 42 | } 43 | 44 | // 创建分布式随机森林实例 45 | DistributedForest forest; 46 | 47 | // 加载模型 48 | if (is_master) { 49 | std::cout << "加载模型...\n"; 50 | try { 51 | forest.load_model("random_forest_model.bin"); 52 | std::cout << "模型加载成功!\n\n"; 53 | } catch (const std::exception& e) { 54 | std::cerr << "模型加载失败:" << e.what() << "\n"; 55 | MPI_Abort(MPI_COMM_WORLD, 1); 56 | return 1; 57 | } 58 | } 59 | 60 | // 预测 61 | if (is_master) { 62 | arma::vec y_pred = forest.predict(X); 63 | 64 | // 计算性能指标 65 | Metrics metrics; 66 | auto regression_metrics = metrics.calculate_regression_metrics(y, y_pred); 67 | 68 | std::cout << "预测完成!性能指标:\n"; 69 | std::cout << "MSE: " << regression_metrics.mse << "\n"; 70 | std::cout << "RMSE: " << regression_metrics.rmse << "\n"; 71 | std::cout << "MAE: " << regression_metrics.mae << "\n"; 72 | std::cout << "R²: " << regression_metrics.r2 << "\n"; 73 | std::cout << "解释方差分数: " << regression_metrics.explained_variance << "\n\n"; 74 | 75 | // 输出一些预测示例 76 | std::cout << "预测示例(前5个样本):\n"; 77 | std::cout << "真实值\t\t预测值\t\t误差\n"; 78 | for (size_t i = 0; i < 5 && i < y.n_elem; ++i) { 79 | std::cout << y(i) << "\t\t" 80 | << y_pred(i) << "\t\t" 81 | << std::abs(y(i) - y_pred(i)) << "\n"; 82 | } 83 | } 84 | } catch (const std::exception& e) { 85 | std::cerr << "错误:" << e.what() << std::endl; 86 | MPI_Abort(MPI_COMM_WORLD, 1); 87 | } 88 | 89 | // 清理MPI 90 | MPI_Finalize(); 91 | return 0; 92 | } -------------------------------------------------------------------------------- /Armadillo线性回归模型/src/utils/data_loader.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace rf { 7 | 8 | /** 9 | * @brief 数据加载器类 10 | */ 11 | class DataLoader { 12 | public: 13 | /** 14 | * @brief 批次迭代器类 15 | */ 16 | class BatchIterator { 17 | public: 18 | /** 19 | * @brief 构造函数 20 | * @param X 特征矩阵 21 | * @param y 目标值 22 | * @param batch_size 批次大小 23 | */ 24 | BatchIterator(const arma::mat& X, const arma::vec& y, arma::uword batch_size); 25 | 26 | /** 27 | * @brief 检查是否还有下一个批次 28 | * @return 是否有下一个批次 29 | */ 30 | bool has_next() const; 31 | 32 | /** 33 | * @brief 获取下一个批次 34 | * @return 是否成功获取下一个批次 35 | */ 36 | bool next(); 37 | 38 | /** 39 | * @brief 获取当前批次的特征矩阵 40 | * @return 当前批次的特征矩阵 41 | */ 42 | const arma::mat& get_current_batch() const { return current_batch_; } 43 | 44 | /** 45 | * @brief 获取当前批次的标签 46 | * @return 当前批次的标签 47 | */ 48 | const arma::vec& get_current_labels() const { return current_labels_; } 49 | 50 | private: 51 | const arma::mat& X_; ///< 特征矩阵引用 52 | const arma::vec& y_; ///< 目标值引用 53 | arma::uword batch_size_; ///< 批次大小 54 | arma::uword current_pos_; ///< 当前位置 55 | arma::mat current_batch_; ///< 当前批次的特征矩阵 56 | arma::vec current_labels_; ///< 当前批次的标签 57 | }; 58 | 59 | /** 60 | * @brief 构造函数 61 | * @param batch_size 批次大小 62 | */ 63 | explicit DataLoader(arma::uword batch_size = 32); 64 | 65 | /** 66 | * @brief 从CSV文件加载数据 67 | * @param filename 文件名 68 | * @param has_header 是否有表头 69 | * @return pair<特征矩阵, 目标值向量> 70 | */ 71 | std::pair load_csv(const std::string& filename, bool has_header = true); 72 | 73 | /** 74 | * @brief 使用内存映射加载大文件 75 | * @param filename 文件名 76 | * @param has_header 是否有表头 77 | * @return pair<特征矩阵, 目标值向量> 78 | */ 79 | std::pair load_large_csv(const std::string& filename, bool has_header = true); 80 | 81 | /** 82 | * @brief 获取批次迭代器 83 | * @param X 特征矩阵 84 | * @param y 目标值向量 85 | * @return BatchIterator对象 86 | */ 87 | BatchIterator get_batch_iterator(const arma::mat& X, const arma::vec& y); 88 | 89 | /** 90 | * @brief 特征标准化 91 | * @param X 输入特征矩阵 92 | * @return 标准化后的特征矩阵 93 | */ 94 | arma::mat standardize(const arma::mat& X); 95 | 96 | /** 97 | * @brief 特征归一化 98 | * @param X 输入特征矩阵 99 | * @return 归一化后的特征矩阵 100 | */ 101 | arma::mat normalize(const arma::mat& X); 102 | 103 | /** 104 | * @brief 处理缺失值 105 | * @param X 输入特征矩阵 106 | * @param strategy 处理策略("mean", "median", "mode") 107 | * @return 处理后的特征矩阵 108 | */ 109 | arma::mat handle_missing_values(const arma::mat& X, const std::string& strategy = "mean"); 110 | 111 | /** 112 | * @brief 下载加州房价数据集 113 | * @param save_path 保存路径 114 | * @return pair<特征矩阵, 目标值向量> 115 | */ 116 | static std::pair load_california_housing(const std::string& save_path = "data/california_housing.csv"); 117 | 118 | private: 119 | arma::uword batch_size_; ///< 批处理大小 120 | arma::vec mean_; ///< 特征均值 121 | arma::vec std_; ///< 特征标准差 122 | arma::vec min_; ///< 特征最小值 123 | arma::vec max_; ///< 特征最大值 124 | }; 125 | 126 | } // namespace rf -------------------------------------------------------------------------------- /C++实现GNN/README.md: -------------------------------------------------------------------------------- 1 | 编译: 2 | 3 | ```bash 4 | g++ -std=c++11 -I/usr/local/Homebrew/Cellar/eigen/3.4.0_1/include/eigen3 gnn.cpp -o gnn && ./gnn 5 | 6 | ``` 7 | 8 | 让我解释一下输出结果: 9 | 10 | 1. **初始节点特征**: 11 | - 每个节点都有一个3维的特征向量 12 | - 节点0:[1, 0, 0] 13 | - 节点1:[0, 1, 0] 14 | - 节点2:[0, 0, 1] 15 | - 节点3:[1, 1, 1] 16 | 2. **GNN层输出特征**: 17 | - GNN层将3维特征转换为2维特征 18 | - 输出显示了每个节点的新特征 19 | - 由于使用了ReLU激活函数,所有负值都被设为0 20 | - 每个节点的新特征都考虑了其邻居节点的信息 21 | 22 | 这个简单的GNN实现展示了图神经网络的基本原理: 23 | 24 | 1. 特征聚合:每个节点收集自己和邻居的特征 25 | 2. 特征变换:通过权重矩阵进行线性变换 26 | 3. 非线性激活:使用ReLU函数引入非线性 -------------------------------------------------------------------------------- /C++实现GNN/gnn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现GNN/gnn -------------------------------------------------------------------------------- /C++实现GNN/gnn.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace std; 8 | using namespace Eigen; 9 | 10 | // 图结构的定义 11 | class Graph { 12 | private: 13 | int num_nodes; 14 | vector > adjacency_list; 15 | MatrixXd node_features; 16 | 17 | public: 18 | Graph(int n) : num_nodes(n) { 19 | adjacency_list.resize(n); 20 | node_features = MatrixXd::Zero(n, 0); 21 | } 22 | 23 | void add_edge(int from, int to) { 24 | if (from >= 0 && from < num_nodes && to >= 0 && to < num_nodes) { 25 | adjacency_list[from].push_back(to); 26 | adjacency_list[to].push_back(from); // 无向图 27 | } 28 | } 29 | 30 | void set_node_features(const MatrixXd& features) { 31 | node_features = features; 32 | } 33 | 34 | MatrixXd get_node_features() const { 35 | return node_features; 36 | } 37 | 38 | vector > get_adjacency_list() const { 39 | return adjacency_list; 40 | } 41 | 42 | int get_num_nodes() const { 43 | return num_nodes; 44 | } 45 | }; 46 | 47 | // GNN层的定义 48 | class GNNLayer { 49 | private: 50 | MatrixXd weight_matrix; 51 | int input_dim; 52 | int output_dim; 53 | 54 | public: 55 | GNNLayer(int in_dim, int out_dim) : input_dim(in_dim), output_dim(out_dim) { 56 | // 随机初始化权重 57 | random_device rd; 58 | mt19937 gen(rd()); 59 | normal_distribution distribution(0.0, 0.1); 60 | 61 | weight_matrix = MatrixXd::Zero(input_dim, output_dim); 62 | for(int i = 0; i < input_dim; i++) { 63 | for(int j = 0; j < output_dim; j++) { 64 | weight_matrix(i, j) = distribution(gen); 65 | } 66 | } 67 | } 68 | 69 | // ReLU激活函数 70 | static double relu(double x) { 71 | return max(0.0, x); 72 | } 73 | 74 | MatrixXd forward(const Graph& graph) { 75 | MatrixXd features = graph.get_node_features(); 76 | vector > adj_list = graph.get_adjacency_list(); 77 | int num_nodes = graph.get_num_nodes(); 78 | 79 | // 对每个节点,聚合邻居的特征 80 | MatrixXd aggregated_features = MatrixXd::Zero(num_nodes, input_dim); 81 | for(int i = 0; i < num_nodes; i++) { 82 | // 包含自身特征 83 | aggregated_features.row(i) = features.row(i); 84 | 85 | // 聚合邻居特征 86 | for(size_t j = 0; j < adj_list[i].size(); j++) { 87 | int neighbor = adj_list[i][j]; 88 | aggregated_features.row(i) += features.row(neighbor); 89 | } 90 | 91 | // 归一化 92 | aggregated_features.row(i) /= (adj_list[i].size() + 1.0); 93 | } 94 | 95 | // 线性变换 96 | MatrixXd transformed = aggregated_features * weight_matrix; 97 | 98 | // 应用ReLU激活函数 99 | for(int i = 0; i < transformed.rows(); i++) { 100 | for(int j = 0; j < transformed.cols(); j++) { 101 | transformed(i, j) = relu(transformed(i, j)); 102 | } 103 | } 104 | 105 | return transformed; 106 | } 107 | }; 108 | 109 | int main() { 110 | // 创建示例图 111 | Graph graph(4); // 4个节点的图 112 | 113 | // 添加边 114 | graph.add_edge(0, 1); 115 | graph.add_edge(1, 2); 116 | graph.add_edge(2, 3); 117 | graph.add_edge(3, 0); 118 | 119 | // 设置初始节点特征(每个节点3维特征) 120 | MatrixXd initial_features(4, 3); 121 | initial_features << 1.0, 0.0, 0.0, 122 | 0.0, 1.0, 0.0, 123 | 0.0, 0.0, 1.0, 124 | 1.0, 1.0, 1.0; 125 | graph.set_node_features(initial_features); 126 | 127 | // 创建GNN层(输入维度3,输出维度2) 128 | GNNLayer gnn_layer(3, 2); 129 | 130 | // 执行前向传播 131 | cout << "初始节点特征:" << endl; 132 | cout << graph.get_node_features() << endl << endl; 133 | 134 | MatrixXd output = gnn_layer.forward(graph); 135 | 136 | cout << "GNN层输出特征:" << endl; 137 | cout << output << endl; 138 | 139 | return 0; 140 | } -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(decision_tree_iris) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | # 添加可执行文件 8 | add_executable(decision_tree 9 | src/main.cpp 10 | src/DecisionTree.cpp 11 | ) 12 | 13 | # 添加头文件目录 14 | target_include_directories(decision_tree PRIVATE src) -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CMakeCCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_C_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc") 2 | set(CMAKE_C_COMPILER_ARG1 "") 3 | set(CMAKE_C_COMPILER_ID "AppleClang") 4 | set(CMAKE_C_COMPILER_VERSION "15.0.0.15000309") 5 | set(CMAKE_C_COMPILER_VERSION_INTERNAL "") 6 | set(CMAKE_C_COMPILER_WRAPPER "") 7 | set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") 8 | set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") 9 | set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") 10 | set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") 11 | set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") 12 | set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") 13 | set(CMAKE_C17_COMPILE_FEATURES "c_std_17") 14 | set(CMAKE_C23_COMPILE_FEATURES "c_std_23") 15 | 16 | set(CMAKE_C_PLATFORM_ID "Darwin") 17 | set(CMAKE_C_SIMULATE_ID "") 18 | set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") 19 | set(CMAKE_C_SIMULATE_VERSION "") 20 | 21 | 22 | 23 | 24 | set(CMAKE_AR "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar") 25 | set(CMAKE_C_COMPILER_AR "") 26 | set(CMAKE_RANLIB "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib") 27 | set(CMAKE_C_COMPILER_RANLIB "") 28 | set(CMAKE_LINKER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld") 29 | set(CMAKE_MT "") 30 | set(CMAKE_COMPILER_IS_GNUCC ) 31 | set(CMAKE_C_COMPILER_LOADED 1) 32 | set(CMAKE_C_COMPILER_WORKS TRUE) 33 | set(CMAKE_C_ABI_COMPILED TRUE) 34 | 35 | set(CMAKE_C_COMPILER_ENV_VAR "CC") 36 | 37 | set(CMAKE_C_COMPILER_ID_RUN 1) 38 | set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) 39 | set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) 40 | set(CMAKE_C_LINKER_PREFERENCE 10) 41 | 42 | # Save compiler ABI information. 43 | set(CMAKE_C_SIZEOF_DATA_PTR "8") 44 | set(CMAKE_C_COMPILER_ABI "") 45 | set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") 46 | set(CMAKE_C_LIBRARY_ARCHITECTURE "") 47 | 48 | if(CMAKE_C_SIZEOF_DATA_PTR) 49 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") 50 | endif() 51 | 52 | if(CMAKE_C_COMPILER_ABI) 53 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") 54 | endif() 55 | 56 | if(CMAKE_C_LIBRARY_ARCHITECTURE) 57 | set(CMAKE_LIBRARY_ARCHITECTURE "") 58 | endif() 59 | 60 | set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") 61 | if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) 62 | set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") 63 | endif() 64 | 65 | 66 | 67 | 68 | 69 | set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/include;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/include;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include") 70 | set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "") 71 | set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/lib;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/lib/swift") 72 | set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/System/Library/Frameworks") 73 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CMakeDetermineCompilerABI_C.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CMakeDetermineCompilerABI_C.bin -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CMakeDetermineCompilerABI_CXX.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CMakeDetermineCompilerABI_CXX.bin -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CMakeSystem.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_HOST_SYSTEM "Darwin-23.2.0") 2 | set(CMAKE_HOST_SYSTEM_NAME "Darwin") 3 | set(CMAKE_HOST_SYSTEM_VERSION "23.2.0") 4 | set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") 5 | 6 | 7 | 8 | set(CMAKE_SYSTEM "Darwin-23.2.0") 9 | set(CMAKE_SYSTEM_NAME "Darwin") 10 | set(CMAKE_SYSTEM_VERSION "23.2.0") 11 | set(CMAKE_SYSTEM_PROCESSOR "x86_64") 12 | 13 | set(CMAKE_CROSSCOMPILING "FALSE") 14 | 15 | set(CMAKE_SYSTEM_LOADED 1) 16 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CompilerIdC/CMakeCCompilerId.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CompilerIdC/CMakeCCompilerId.o -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CompilerIdCXX/CMakeCXXCompilerId.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/3.26.4/CompilerIdCXX/CMakeCXXCompilerId.o -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/CMakeDirectoryInformation.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.26 3 | 4 | # Relative path conversion top directories. 5 | set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/zhulei/qt_project/picture_alter/decision_tree_iris") 6 | set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/zhulei/qt_project/picture_alter/decision_tree_iris/build") 7 | 8 | # Force unix paths in dependencies. 9 | set(CMAKE_FORCE_UNIX_PATHS 1) 10 | 11 | 12 | # The C and CXX include file regular expressions for this directory. 13 | set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") 14 | set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") 15 | set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) 16 | set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) 17 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/TargetDirectories.txt: -------------------------------------------------------------------------------- 1 | /Users/zhulei/qt_project/picture_alter/decision_tree_iris/build/CMakeFiles/decision_tree.dir 2 | /Users/zhulei/qt_project/picture_alter/decision_tree_iris/build/CMakeFiles/edit_cache.dir 3 | /Users/zhulei/qt_project/picture_alter/decision_tree_iris/build/CMakeFiles/rebuild_cache.dir 4 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/cmake.check_cache: -------------------------------------------------------------------------------- 1 | # This file is generated by cmake for dependency checking of the CMakeCache.txt file 2 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Consider dependencies only in project. 3 | set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) 4 | 5 | # The set of languages for which implicit dependencies are needed: 6 | set(CMAKE_DEPENDS_LANGUAGES 7 | ) 8 | 9 | # The set of dependency files which are needed: 10 | set(CMAKE_DEPENDS_DEPENDENCY_FILES 11 | "/Users/zhulei/qt_project/picture_alter/decision_tree_iris/src/DecisionTree.cpp" "CMakeFiles/decision_tree.dir/src/DecisionTree.cpp.o" "gcc" "CMakeFiles/decision_tree.dir/src/DecisionTree.cpp.o.d" 12 | "/Users/zhulei/qt_project/picture_alter/decision_tree_iris/src/main.cpp" "CMakeFiles/decision_tree.dir/src/main.cpp.o" "gcc" "CMakeFiles/decision_tree.dir/src/main.cpp.o.d" 13 | ) 14 | 15 | # Targets to which this target links which contain Fortran sources. 16 | set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES 17 | ) 18 | 19 | # Fortran module output directory. 20 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 21 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/decision_tree.dir/src/DecisionTree.cpp.o" 3 | "CMakeFiles/decision_tree.dir/src/DecisionTree.cpp.o.d" 4 | "CMakeFiles/decision_tree.dir/src/main.cpp.o" 5 | "CMakeFiles/decision_tree.dir/src/main.cpp.o.d" 6 | "decision_tree" 7 | "decision_tree.pdb" 8 | ) 9 | 10 | # Per-language clean rules from dependency scanning. 11 | foreach(lang CXX) 12 | include(CMakeFiles/decision_tree.dir/cmake_clean_${lang}.cmake OPTIONAL) 13 | endforeach() 14 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/compiler_depend.make: -------------------------------------------------------------------------------- 1 | # Empty compiler generated dependencies file for decision_tree. 2 | # This may be replaced when dependencies are built. 3 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/compiler_depend.ts: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Timestamp file for compiler generated dependencies management for decision_tree. 3 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/depend.make: -------------------------------------------------------------------------------- 1 | # Empty dependencies file for decision_tree. 2 | # This may be replaced when dependencies are built. 3 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.26 3 | 4 | # compile CXX with /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ 5 | CXX_DEFINES = 6 | 7 | CXX_INCLUDES = -I/Users/zhulei/qt_project/picture_alter/decision_tree_iris/src 8 | 9 | CXX_FLAGS = -std=gnu++17 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 10 | 11 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/link.txt: -------------------------------------------------------------------------------- 1 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/decision_tree.dir/src/main.cpp.o CMakeFiles/decision_tree.dir/src/DecisionTree.cpp.o -o decision_tree 2 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 1 2 | CMAKE_PROGRESS_2 = 2 3 | CMAKE_PROGRESS_3 = 3 4 | 5 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/src/DecisionTree.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/src/DecisionTree.cpp.o -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/src/main.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/decision_tree.dir/src/main.cpp.o -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/CMakeFiles/progress.marks: -------------------------------------------------------------------------------- 1 | 3 2 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/cmake_install.cmake: -------------------------------------------------------------------------------- 1 | # Install script for directory: /Users/zhulei/qt_project/picture_alter/decision_tree_iris 2 | 3 | # Set the install prefix 4 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 5 | set(CMAKE_INSTALL_PREFIX "/usr/local/Homebrew") 6 | endif() 7 | string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 8 | 9 | # Set the install configuration name. 10 | if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) 11 | if(BUILD_TYPE) 12 | string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" 13 | CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") 14 | else() 15 | set(CMAKE_INSTALL_CONFIG_NAME "") 16 | endif() 17 | message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") 18 | endif() 19 | 20 | # Set the component getting installed. 21 | if(NOT CMAKE_INSTALL_COMPONENT) 22 | if(COMPONENT) 23 | message(STATUS "Install component: \"${COMPONENT}\"") 24 | set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") 25 | else() 26 | set(CMAKE_INSTALL_COMPONENT) 27 | endif() 28 | endif() 29 | 30 | # Is this installation the result of a crosscompile? 31 | if(NOT DEFINED CMAKE_CROSSCOMPILING) 32 | set(CMAKE_CROSSCOMPILING "FALSE") 33 | endif() 34 | 35 | # Set default install directory permissions. 36 | if(NOT DEFINED CMAKE_OBJDUMP) 37 | set(CMAKE_OBJDUMP "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/objdump") 38 | endif() 39 | 40 | if(CMAKE_INSTALL_COMPONENT) 41 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") 42 | else() 43 | set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") 44 | endif() 45 | 46 | string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT 47 | "${CMAKE_INSTALL_MANIFEST_FILES}") 48 | file(WRITE "/Users/zhulei/qt_project/picture_alter/decision_tree_iris/build/${CMAKE_INSTALL_MANIFEST}" 49 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 50 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/decision_tree: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现一个基于ID3:C4.5算法的决策树分类器/build/decision_tree -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/decision_tree.dot: -------------------------------------------------------------------------------- 1 | digraph DecisionTree { 2 | node0 [label="特征 2 <= 3.800000"]; 3 | node1 [label="Iris-setosa"]; 4 | node0 -> node1 [label="是"]; 5 | node2 [label="特征 3 <= 1.753846"]; 6 | node3 [label="特征 0 <= 6.214286"]; 7 | node4 [label="特征 1 <= 2.600000"]; 8 | node5 [label="Iris-virginica"]; 9 | node4 -> node5 [label="是"]; 10 | node6 [label="Iris-versicolor"]; 11 | node4 -> node6 [label="否"]; 12 | node3 -> node4 [label="是"]; 13 | node7 [label="Iris-versicolor"]; 14 | node3 -> node7 [label="否"]; 15 | node2 -> node3 [label="是"]; 16 | node8 [label="特征 1 <= 3.066667"]; 17 | node9 [label="Iris-virginica"]; 18 | node8 -> node9 [label="是"]; 19 | node10 [label="Iris-virginica "]; 20 | node8 -> node10 [label="否"]; 21 | node2 -> node8 [label="否"]; 22 | node0 -> node2 [label="否"]; 23 | } 24 | -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/build/iris.csv: -------------------------------------------------------------------------------- 1 | 5.1,3.5,1.4,0.2,Iris-setosa 2 | 4.9,3.0,1.4,0.2,Iris-setosa 3 | 4.7,3.2,1.3,0.2,Iris-setosa 4 | 4.6,3.1,1.5,0.2,Iris-setosa 5 | 5.0,3.6,1.4,0.2,Iris-setosa 6 | 5.4,3.9,1.7,0.4,Iris-setosa 7 | 4.6,3.4,1.4,0.3,Iris-setosa 8 | 5.0,3.4,1.5,0.2,Iris-setosa 9 | 4.4,2.9,1.4,0.2,Iris-setosa 10 | 4.9,3.1,1.5,0.1,Iris-setosa 11 | 7.0,3.2,4.7,1.4,Iris-versicolor 12 | 6.4,3.2,4.5,1.5,Iris-versicolor 13 | 6.9,3.1,4.9,1.5,Iris-versicolor 14 | 5.5,2.3,4.0,1.3,Iris-versicolor 15 | 6.5,2.8,4.6,1.5,Iris-versicolor 16 | 5.7,2.8,4.5,1.3,Iris-versicolor 17 | 6.3,3.3,4.7,1.6,Iris-versicolor 18 | 4.9,2.4,3.3,1.0,Iris-versicolor 19 | 6.6,2.9,4.6,1.3,Iris-versicolor 20 | 5.2,2.7,3.9,1.4,Iris-versicolor 21 | 6.3,3.3,6.0,2.5,Iris-virginica 22 | 5.8,2.7,5.1,1.9,Iris-virginica 23 | 7.1,3.0,5.9,2.1,Iris-virginica 24 | 6.3,2.9,5.6,1.8,Iris-virginica 25 | 6.5,3.0,5.8,2.2,Iris-virginica 26 | 7.6,3.0,6.6,2.1,Iris-virginica 27 | 4.9,2.5,4.5,1.7,Iris-virginica 28 | 7.3,2.9,6.3,1.8,Iris-virginica 29 | 6.7,2.5,5.8,1.8,Iris-virginica 30 | 7.2,3.6,6.1,2.5,Iris-virginica -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/decision_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现一个基于ID3:C4.5算法的决策树分类器/decision_tree.png -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/iris.csv: -------------------------------------------------------------------------------- 1 | 5.1,3.5,1.4,0.2,Iris-setosa 2 | 4.9,3.0,1.4,0.2,Iris-setosa 3 | 4.7,3.2,1.3,0.2,Iris-setosa 4 | 4.6,3.1,1.5,0.2,Iris-setosa 5 | 5.0,3.6,1.4,0.2,Iris-setosa 6 | 5.4,3.9,1.7,0.4,Iris-setosa 7 | 4.6,3.4,1.4,0.3,Iris-setosa 8 | 5.0,3.4,1.5,0.2,Iris-setosa 9 | 4.4,2.9,1.4,0.2,Iris-setosa 10 | 4.9,3.1,1.5,0.1,Iris-setosa 11 | 7.0,3.2,4.7,1.4,Iris-versicolor 12 | 6.4,3.2,4.5,1.5,Iris-versicolor 13 | 6.9,3.1,4.9,1.5,Iris-versicolor 14 | 5.5,2.3,4.0,1.3,Iris-versicolor 15 | 6.5,2.8,4.6,1.5,Iris-versicolor 16 | 5.7,2.8,4.5,1.3,Iris-versicolor 17 | 6.3,3.3,4.7,1.6,Iris-versicolor 18 | 4.9,2.4,3.3,1.0,Iris-versicolor 19 | 6.6,2.9,4.6,1.3,Iris-versicolor 20 | 5.2,2.7,3.9,1.4,Iris-versicolor 21 | 6.3,3.3,6.0,2.5,Iris-virginica 22 | 5.8,2.7,5.1,1.9,Iris-virginica 23 | 7.1,3.0,5.9,2.1,Iris-virginica 24 | 6.3,2.9,5.6,1.8,Iris-virginica 25 | 6.5,3.0,5.8,2.2,Iris-virginica 26 | 7.6,3.0,6.6,2.1,Iris-virginica 27 | 4.9,2.5,4.5,1.7,Iris-virginica 28 | 7.3,2.9,6.3,1.8,Iris-virginica 29 | 6.7,2.5,5.8,1.8,Iris-virginica 30 | 7.2,3.6,6.1,2.5,Iris-virginica -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/src/DecisionTree.h: -------------------------------------------------------------------------------- 1 | #ifndef DECISION_TREE_H 2 | #define DECISION_TREE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Node.h" 8 | 9 | class DecisionTree { 10 | public: 11 | DecisionTree(bool useC45 = false, int maxDepth = 10); 12 | ~DecisionTree(); 13 | 14 | // 训练决策树 15 | void train(const std::vector>& data, 16 | const std::vector& labels); 17 | 18 | // 预测单个样本 19 | std::string predict(const std::vector& sample) const; 20 | 21 | // 导出决策树为DOT格式 22 | void exportToDot(const std::string& filename) const; 23 | 24 | private: 25 | std::shared_ptr root; 26 | bool useC45; // 是否使用C4.5算法(否则使用ID3) 27 | int maxDepth; // 最大树深度 28 | 29 | // 递归构建决策树 30 | std::shared_ptr buildTree( 31 | const std::vector>& data, 32 | const std::vector& labels, 33 | const std::vector& availableFeatures, 34 | int depth 35 | ); 36 | 37 | // 计算信息熵 38 | double calculateEntropy(const std::vector& labels) const; 39 | 40 | // 计算信息增益 41 | double calculateInformationGain( 42 | const std::vector>& data, 43 | const std::vector& labels, 44 | int featureIndex 45 | ) const; 46 | 47 | // 计算信息增益率(C4.5算法使用) 48 | double calculateInformationGainRatio( 49 | const std::vector>& data, 50 | const std::vector& labels, 51 | int featureIndex 52 | ) const; 53 | 54 | // 递归生成DOT格式字符串 55 | void generateDot(std::shared_ptr node, std::string& dot, int& nodeCount) const; 56 | }; 57 | 58 | #endif // DECISION_TREE_H -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/src/Node.h: -------------------------------------------------------------------------------- 1 | #ifndef NODE_H 2 | #define NODE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Node { 9 | public: 10 | bool isLeaf; // 是否为叶子节点 11 | int attributeIndex; // 分裂属性的索引 12 | double splitValue; // 分裂值 13 | std::string className; // 类别名称(叶子节点) 14 | std::vector> children; // 子节点 15 | 16 | Node(bool leaf = false) : 17 | isLeaf(leaf), 18 | attributeIndex(-1), 19 | splitValue(0.0) {} 20 | }; 21 | 22 | #endif // NODE_H -------------------------------------------------------------------------------- /C++实现一个基于ID3:C4.5算法的决策树分类器/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "DecisionTree.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // 加载鸢尾花数据集 9 | bool loadIrisData( 10 | const std::string& filename, 11 | std::vector>& data, 12 | std::vector& labels) { 13 | 14 | std::ifstream file(filename); 15 | if (!file.is_open()) { 16 | std::cerr << "无法打开文件: " << filename << std::endl; 17 | return false; 18 | } 19 | 20 | std::string line; 21 | while (std::getline(file, line)) { 22 | std::stringstream ss(line); 23 | std::string value; 24 | std::vector sample; 25 | 26 | // 读取4个特征值 27 | for (int i = 0; i < 4; ++i) { 28 | std::getline(ss, value, ','); 29 | sample.push_back(std::stod(value)); 30 | } 31 | 32 | // 读取类别标签 33 | std::getline(ss, value, ','); 34 | 35 | data.push_back(sample); 36 | labels.push_back(value); 37 | } 38 | 39 | return true; 40 | } 41 | 42 | // 将数据集随机分为训练集和测试集 43 | void splitDataset( 44 | const std::vector>& data, 45 | const std::vector& labels, 46 | double trainRatio, 47 | std::vector>& trainData, 48 | std::vector& trainLabels, 49 | std::vector>& testData, 50 | std::vector& testLabels) { 51 | 52 | std::vector indices(data.size()); 53 | for (size_t i = 0; i < indices.size(); ++i) { 54 | indices[i] = i; 55 | } 56 | 57 | // 随机打乱索引 58 | std::random_device rd; 59 | std::mt19937 gen(rd()); 60 | std::shuffle(indices.begin(), indices.end(), gen); 61 | 62 | size_t trainSize = static_cast(data.size() * trainRatio); 63 | 64 | for (size_t i = 0; i < indices.size(); ++i) { 65 | if (i < trainSize) { 66 | trainData.push_back(data[indices[i]]); 67 | trainLabels.push_back(labels[indices[i]]); 68 | } else { 69 | testData.push_back(data[indices[i]]); 70 | testLabels.push_back(labels[indices[i]]); 71 | } 72 | } 73 | } 74 | 75 | int main() { 76 | // 加载数据 77 | std::vector> data; 78 | std::vector labels; 79 | 80 | if (!loadIrisData("iris.csv", data, labels)) { 81 | return 1; 82 | } 83 | 84 | // 分割数据集 85 | std::vector> trainData, testData; 86 | std::vector trainLabels, testLabels; 87 | splitDataset(data, labels, 0.7, trainData, trainLabels, testData, testLabels); 88 | 89 | // 创建并训练决策树(使用C4.5算法) 90 | DecisionTree tree(true, 5); 91 | tree.train(trainData, trainLabels); 92 | 93 | // 导出决策树可视化 94 | tree.exportToDot("decision_tree.dot"); 95 | std::cout << "决策树已导出到 decision_tree.dot" << std::endl; 96 | 97 | // 在测试集上进行预测 98 | int correct = 0; 99 | for (size_t i = 0; i < testData.size(); ++i) { 100 | std::string predicted = tree.predict(testData[i]); 101 | if (predicted == testLabels[i]) { 102 | correct++; 103 | } 104 | std::cout << "样本 " << i << ": 预测=" << predicted 105 | << ", 实际=" << testLabels[i] << std::endl; 106 | } 107 | 108 | // 计算准确率 109 | double accuracy = static_cast(correct) / testData.size(); 110 | std::cout << "测试集准确率: " << accuracy * 100 << "%" << std::endl; 111 | 112 | return 0; 113 | } -------------------------------------------------------------------------------- /C++实现手写数字识别.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现手写数字识别.zip -------------------------------------------------------------------------------- /C++实现股票价格预测系统/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(StockPricePredictor) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | # 查找必要的包 8 | find_package(Boost REQUIRED COMPONENTS date_time) 9 | find_package(Eigen3 REQUIRED) 10 | 11 | # 添加头文件目录 12 | include_directories(${PROJECT_SOURCE_DIR}/include) 13 | include_directories(${Boost_INCLUDE_DIRS}) 14 | include_directories(${EIGEN3_INCLUDE_DIR}) 15 | 16 | # 添加源文件 17 | file(GLOB SOURCES "src/*.cpp") 18 | 19 | # 创建可执行文件 20 | add_executable(${PROJECT_NAME} ${SOURCES}) 21 | 22 | # 链接库 23 | target_link_libraries(${PROJECT_NAME} 24 | ${Boost_LIBRARIES} 25 | Eigen3::Eigen 26 | ) -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CMakeCCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_C_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc") 2 | set(CMAKE_C_COMPILER_ARG1 "") 3 | set(CMAKE_C_COMPILER_ID "AppleClang") 4 | set(CMAKE_C_COMPILER_VERSION "15.0.0.15000309") 5 | set(CMAKE_C_COMPILER_VERSION_INTERNAL "") 6 | set(CMAKE_C_COMPILER_WRAPPER "") 7 | set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") 8 | set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") 9 | set(CMAKE_C_STANDARD_LATEST "23") 10 | set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") 11 | set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") 12 | set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") 13 | set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") 14 | set(CMAKE_C17_COMPILE_FEATURES "c_std_17") 15 | set(CMAKE_C23_COMPILE_FEATURES "c_std_23") 16 | 17 | set(CMAKE_C_PLATFORM_ID "Darwin") 18 | set(CMAKE_C_SIMULATE_ID "") 19 | set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") 20 | set(CMAKE_C_SIMULATE_VERSION "") 21 | 22 | 23 | 24 | 25 | set(CMAKE_AR "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar") 26 | set(CMAKE_C_COMPILER_AR "") 27 | set(CMAKE_RANLIB "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib") 28 | set(CMAKE_C_COMPILER_RANLIB "") 29 | set(CMAKE_LINKER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld") 30 | set(CMAKE_LINKER_LINK "") 31 | set(CMAKE_LINKER_LLD "") 32 | set(CMAKE_C_COMPILER_LINKER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld") 33 | set(CMAKE_C_COMPILER_LINKER_ID "AppleClang") 34 | set(CMAKE_C_COMPILER_LINKER_VERSION 1053.12) 35 | set(CMAKE_C_COMPILER_LINKER_FRONTEND_VARIANT GNU) 36 | set(CMAKE_MT "") 37 | set(CMAKE_TAPI "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/tapi") 38 | set(CMAKE_COMPILER_IS_GNUCC ) 39 | set(CMAKE_C_COMPILER_LOADED 1) 40 | set(CMAKE_C_COMPILER_WORKS TRUE) 41 | set(CMAKE_C_ABI_COMPILED TRUE) 42 | 43 | set(CMAKE_C_COMPILER_ENV_VAR "CC") 44 | 45 | set(CMAKE_C_COMPILER_ID_RUN 1) 46 | set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) 47 | set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) 48 | set(CMAKE_C_LINKER_PREFERENCE 10) 49 | set(CMAKE_C_LINKER_DEPFILE_SUPPORTED ) 50 | 51 | # Save compiler ABI information. 52 | set(CMAKE_C_SIZEOF_DATA_PTR "8") 53 | set(CMAKE_C_COMPILER_ABI "") 54 | set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") 55 | set(CMAKE_C_LIBRARY_ARCHITECTURE "") 56 | 57 | if(CMAKE_C_SIZEOF_DATA_PTR) 58 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") 59 | endif() 60 | 61 | if(CMAKE_C_COMPILER_ABI) 62 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") 63 | endif() 64 | 65 | if(CMAKE_C_LIBRARY_ARCHITECTURE) 66 | set(CMAKE_LIBRARY_ARCHITECTURE "") 67 | endif() 68 | 69 | set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") 70 | if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) 71 | set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") 72 | endif() 73 | 74 | 75 | 76 | 77 | 78 | set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/include;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/include;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include") 79 | set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "") 80 | set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/lib;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/lib/swift") 81 | set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/System/Library/Frameworks") 82 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CMakeDetermineCompilerABI_C.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CMakeDetermineCompilerABI_C.bin -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CMakeDetermineCompilerABI_CXX.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CMakeDetermineCompilerABI_CXX.bin -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CMakeSystem.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_HOST_SYSTEM "Darwin-23.2.0") 2 | set(CMAKE_HOST_SYSTEM_NAME "Darwin") 3 | set(CMAKE_HOST_SYSTEM_VERSION "23.2.0") 4 | set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") 5 | 6 | 7 | 8 | set(CMAKE_SYSTEM "Darwin-23.2.0") 9 | set(CMAKE_SYSTEM_NAME "Darwin") 10 | set(CMAKE_SYSTEM_VERSION "23.2.0") 11 | set(CMAKE_SYSTEM_PROCESSOR "x86_64") 12 | 13 | set(CMAKE_CROSSCOMPILING "FALSE") 14 | 15 | set(CMAKE_SYSTEM_LOADED 1) 16 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CompilerIdC/CMakeCCompilerId.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CompilerIdC/CMakeCCompilerId.o -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CompilerIdCXX/CMakeCXXCompilerId.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现股票价格预测系统/build/CMakeFiles/3.31.5/CompilerIdCXX/CMakeCXXCompilerId.o -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/CMakeDirectoryInformation.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.31 3 | 4 | # Relative path conversion top directories. 5 | set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/zhulei/qt_project/picture_alter") 6 | set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/zhulei/qt_project/picture_alter/build") 7 | 8 | # Force unix paths in dependencies. 9 | set(CMAKE_FORCE_UNIX_PATHS 1) 10 | 11 | 12 | # The C and CXX include file regular expressions for this directory. 13 | set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") 14 | set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") 15 | set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) 16 | set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) 17 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Consider dependencies only in project. 3 | set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) 4 | 5 | # The set of languages for which implicit dependencies are needed: 6 | set(CMAKE_DEPENDS_LANGUAGES 7 | ) 8 | 9 | # The set of dependency files which are needed: 10 | set(CMAKE_DEPENDS_DEPENDENCY_FILES 11 | "/Users/zhulei/qt_project/picture_alter/src/arima_model.cpp" "CMakeFiles/StockPricePredictor.dir/src/arima_model.cpp.o" "gcc" "CMakeFiles/StockPricePredictor.dir/src/arima_model.cpp.o.d" 12 | "/Users/zhulei/qt_project/picture_alter/src/data_processor.cpp" "CMakeFiles/StockPricePredictor.dir/src/data_processor.cpp.o" "gcc" "CMakeFiles/StockPricePredictor.dir/src/data_processor.cpp.o.d" 13 | "/Users/zhulei/qt_project/picture_alter/src/main.cpp" "CMakeFiles/StockPricePredictor.dir/src/main.cpp.o" "gcc" "CMakeFiles/StockPricePredictor.dir/src/main.cpp.o.d" 14 | ) 15 | 16 | # Targets to which this target links which contain Fortran sources. 17 | set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES 18 | ) 19 | 20 | # Targets to which this target links which contain Fortran sources. 21 | set(CMAKE_Fortran_TARGET_FORWARD_LINKED_INFO_FILES 22 | ) 23 | 24 | # Fortran module output directory. 25 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 26 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/StockPricePredictor.dir/src/arima_model.cpp.o" 3 | "CMakeFiles/StockPricePredictor.dir/src/arima_model.cpp.o.d" 4 | "CMakeFiles/StockPricePredictor.dir/src/data_processor.cpp.o" 5 | "CMakeFiles/StockPricePredictor.dir/src/data_processor.cpp.o.d" 6 | "CMakeFiles/StockPricePredictor.dir/src/main.cpp.o" 7 | "CMakeFiles/StockPricePredictor.dir/src/main.cpp.o.d" 8 | "StockPricePredictor" 9 | "StockPricePredictor.pdb" 10 | ) 11 | 12 | # Per-language clean rules from dependency scanning. 13 | foreach(lang CXX) 14 | include(CMakeFiles/StockPricePredictor.dir/cmake_clean_${lang}.cmake OPTIONAL) 15 | endforeach() 16 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/compiler_depend.ts: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Timestamp file for compiler generated dependencies management for StockPricePredictor. 3 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/depend.make: -------------------------------------------------------------------------------- 1 | # Empty dependencies file for StockPricePredictor. 2 | # This may be replaced when dependencies are built. 3 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.31 3 | 4 | # compile CXX with /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ 5 | CXX_DEFINES = -DBOOST_DATE_TIME_DYN_LINK -DBOOST_DATE_TIME_NO_LIB 6 | 7 | CXX_INCLUDES = -I/Users/zhulei/qt_project/picture_alter/include -isystem /opt/anaconda3/include -isystem /usr/local/Homebrew/include/eigen3 8 | 9 | CXX_FLAGS = -std=gnu++17 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 10 | 11 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/link.txt: -------------------------------------------------------------------------------- 1 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/StockPricePredictor.dir/src/arima_model.cpp.o CMakeFiles/StockPricePredictor.dir/src/data_processor.cpp.o CMakeFiles/StockPricePredictor.dir/src/main.cpp.o -o StockPricePredictor -Wl,-rpath,/opt/anaconda3/lib /opt/anaconda3/lib/libboost_date_time.dylib 2 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 1 2 | CMAKE_PROGRESS_2 = 2 3 | CMAKE_PROGRESS_3 = 3 4 | CMAKE_PROGRESS_4 = 4 5 | 6 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/src/arima_model.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/src/arima_model.cpp.o -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/src/data_processor.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/src/data_processor.cpp.o -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/src/main.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现股票价格预测系统/build/CMakeFiles/StockPricePredictor.dir/src/main.cpp.o -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/TargetDirectories.txt: -------------------------------------------------------------------------------- 1 | /Users/zhulei/qt_project/picture_alter/build/CMakeFiles/StockPricePredictor.dir 2 | /Users/zhulei/qt_project/picture_alter/build/CMakeFiles/edit_cache.dir 3 | /Users/zhulei/qt_project/picture_alter/build/CMakeFiles/rebuild_cache.dir 4 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/cmake.check_cache: -------------------------------------------------------------------------------- 1 | # This file is generated by cmake for dependency checking of the CMakeCache.txt file 2 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/CMakeFiles/progress.marks: -------------------------------------------------------------------------------- 1 | 4 2 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/StockPricePredictor: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++实现股票价格预测系统/build/StockPricePredictor -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/cmake_install.cmake: -------------------------------------------------------------------------------- 1 | # Install script for directory: /Users/zhulei/qt_project/picture_alter 2 | 3 | # Set the install prefix 4 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 5 | set(CMAKE_INSTALL_PREFIX "/usr/local/Homebrew") 6 | endif() 7 | string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 8 | 9 | # Set the install configuration name. 10 | if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) 11 | if(BUILD_TYPE) 12 | string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" 13 | CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") 14 | else() 15 | set(CMAKE_INSTALL_CONFIG_NAME "") 16 | endif() 17 | message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") 18 | endif() 19 | 20 | # Set the component getting installed. 21 | if(NOT CMAKE_INSTALL_COMPONENT) 22 | if(COMPONENT) 23 | message(STATUS "Install component: \"${COMPONENT}\"") 24 | set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") 25 | else() 26 | set(CMAKE_INSTALL_COMPONENT) 27 | endif() 28 | endif() 29 | 30 | # Is this installation the result of a crosscompile? 31 | if(NOT DEFINED CMAKE_CROSSCOMPILING) 32 | set(CMAKE_CROSSCOMPILING "FALSE") 33 | endif() 34 | 35 | # Set path to fallback-tool for dependency-resolution. 36 | if(NOT DEFINED CMAKE_OBJDUMP) 37 | set(CMAKE_OBJDUMP "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/objdump") 38 | endif() 39 | 40 | string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT 41 | "${CMAKE_INSTALL_MANIFEST_FILES}") 42 | if(CMAKE_INSTALL_LOCAL_ONLY) 43 | file(WRITE "/Users/zhulei/qt_project/picture_alter/build/install_local_manifest.txt" 44 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 45 | endif() 46 | if(CMAKE_INSTALL_COMPONENT) 47 | if(CMAKE_INSTALL_COMPONENT MATCHES "^[a-zA-Z0-9_.+-]+$") 48 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") 49 | else() 50 | string(MD5 CMAKE_INST_COMP_HASH "${CMAKE_INSTALL_COMPONENT}") 51 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INST_COMP_HASH}.txt") 52 | unset(CMAKE_INST_COMP_HASH) 53 | endif() 54 | else() 55 | set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") 56 | endif() 57 | 58 | if(NOT CMAKE_INSTALL_LOCAL_ONLY) 59 | file(WRITE "/Users/zhulei/qt_project/picture_alter/build/${CMAKE_INSTALL_MANIFEST}" 60 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 61 | endif() 62 | -------------------------------------------------------------------------------- /C++实现股票价格预测系统/build/sample_data.csv: -------------------------------------------------------------------------------- 1 | timestamp,price,volume 2 | 2024-01-01 09:30:00,100.50,15000 3 | 2024-01-01 16:00:00,101.20,18500 4 | 2024-01-02 09:30:00,101.80,12000 5 | 2024-01-02 16:00:00,102.30,14500 6 | 2024-01-03 09:30:00,102.10,13000 7 | 2024-01-03 16:00:00,103.40,16800 8 | 2024-01-04 09:30:00,103.60,11500 9 | 2024-01-04 16:00:00,104.20,13200 10 | 2024-01-05 09:30:00,104.50,14700 11 | 2024-01-05 16:00:00,105.30,17300 12 | 2024-01-08 09:30:00,105.80,16200 13 | 2024-01-08 16:00:00,106.40,18900 14 | 2024-01-09 09:30:00,106.20,15400 15 | 2024-01-09 16:00:00,105.90,17800 16 | 2024-01-10 09:30:00,105.70,14300 17 | 2024-01-10 16:00:00,106.80,16500 18 | 2024-01-11 09:30:00,107.20,13800 19 | 2024-01-11 16:00:00,108.10,15900 20 | 2024-01-12 09:30:00,108.40,12600 21 | 2024-01-12 16:00:00,109.20,14200 22 | 2024-01-15 09:30:00,109.50,16700 23 | 2024-01-15 16:00:00,110.30,19100 24 | 2024-01-16 09:30:00,110.80,17500 25 | 2024-01-16 16:00:00,111.40,20300 26 | 2024-01-17 09:30:00,111.20,16900 27 | 2024-01-17 16:00:00,110.90,18400 28 | 2024-01-18 09:30:00,110.70,15200 29 | 2024-01-18 16:00:00,111.80,17600 30 | 2024-01-19 09:30:00,112.20,14800 31 | 2024-01-19 16:00:00,113.10,16300 32 | 2024-01-22 09:30:00,113.40,15600 33 | 2024-01-22 16:00:00,114.20,18200 34 | 2024-01-23 09:30:00,114.50,17100 35 | 2024-01-23 16:00:00,115.30,19800 36 | 2024-01-24 09:30:00,115.80,18400 37 | 2024-01-24 16:00:00,116.40,21200 38 | 2024-01-25 09:30:00,116.20,17600 39 | 2024-01-25 16:00:00,115.90,19300 40 | 2024-01-26 09:30:00,115.70,16500 41 | 2024-01-26 16:00:00,116.80,18700 42 | 2024-01-29 09:30:00,117.20,15900 43 | 2024-01-29 16:00:00,118.10,17400 44 | 2024-01-30 09:30:00,118.40,14700 45 | 2024-01-30 16:00:00,119.20,16800 -------------------------------------------------------------------------------- /C++实现股票价格预测系统/include/arima_model.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace stock_predictor { 11 | 12 | class ARIMAModel { 13 | public: 14 | // 构造函数,初始化ARIMA模型参数 15 | ARIMAModel(int p, int d, int q); 16 | 17 | // 训练模型 18 | void train(const std::vector& data, 19 | const std::vector& timestamps); 20 | 21 | // 预测未来n步的值 22 | std::vector predict(int n_steps); 23 | 24 | // 计算模型参数 25 | void calculateParameters(); 26 | 27 | private: 28 | // ARIMA模型参数 29 | int p_; // AR阶数 30 | int d_; // 差分阶数 31 | int q_; // MA阶数 32 | 33 | // 模型系数 34 | Eigen::VectorXd ar_coefficients_; // AR系数 φ 35 | Eigen::VectorXd ma_coefficients_; // MA系数 θ 36 | double c_; // 常数项 37 | 38 | // 原始数据和处理后的数据 39 | std::vector original_data_; 40 | std::vector differenced_data_; 41 | std::vector residuals_; 42 | 43 | // 辅助函数 44 | std::vector difference(const std::vector& data, int order); 45 | std::vector inverse_difference(const std::vector& diff_data, 46 | const std::vector& original_data, 47 | int order); 48 | 49 | // 计算自相关和偏自相关 50 | Eigen::VectorXd calculateAutoCorrelation(const std::vector& data, int max_lag); 51 | Eigen::VectorXd calculatePartialAutoCorrelation(const std::vector& data, int max_lag); 52 | 53 | // 使用最小二乘法估计参数 54 | void estimateARMAParameters(); 55 | 56 | // 计算均值 57 | double calculateMean(const std::vector& data) const; 58 | }; 59 | 60 | } // namespace stock_predictor -------------------------------------------------------------------------------- /C++实现股票价格预测系统/include/data_processor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace stock_predictor { 9 | 10 | struct StockData { 11 | boost::posix_time::ptime timestamp; 12 | double price; 13 | double volume; 14 | }; 15 | 16 | class DataProcessor { 17 | public: 18 | DataProcessor(size_t window_size = 30); 19 | 20 | // 加载数据 21 | void loadData(const std::string& filename); 22 | 23 | // 获取处理后的时间序列数据 24 | std::vector getProcessedPrices() const; 25 | std::vector getTimestamps() const; 26 | 27 | // 数据预处理 28 | void normalize(); 29 | void removeOutliers(); 30 | void handleMissingValues(); 31 | 32 | // 滑动窗口操作 33 | void updateWindow(const StockData& new_data); 34 | std::vector getWindowData() const; 35 | 36 | private: 37 | std::vector data_; 38 | std::deque sliding_window_; 39 | size_t window_size_; 40 | 41 | // 统计量计算 42 | double calculateMean(const std::vector& data) const; 43 | double calculateStd(const std::vector& data) const; 44 | 45 | // 数据验证 46 | bool isValidPrice(double price) const; 47 | bool isValidTimestamp(const boost::posix_time::ptime& timestamp) const; 48 | }; 49 | 50 | } // namespace stock_predictor -------------------------------------------------------------------------------- /C++实现股票价格预测系统/src/data_processor.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace stock_predictor { 9 | 10 | struct StockData { 11 | boost::posix_time::ptime timestamp; 12 | double price; 13 | double volume; 14 | }; 15 | 16 | class DataProcessor { 17 | public: 18 | DataProcessor(size_t window_size = 30); 19 | 20 | // 加载数据 21 | void loadData(const std::string& filename); 22 | 23 | // 获取处理后的时间序列数据 24 | std::vector getProcessedPrices() const; 25 | std::vector getTimestamps() const; 26 | 27 | // 数据预处理 28 | void normalize(); 29 | void removeOutliers(); 30 | void handleMissingValues(); 31 | 32 | // 获取标准化参数 33 | double getMean() const { return mean_; } 34 | double getStd() const { return std_; } 35 | 36 | // 滑动窗口操作 37 | void updateWindow(const StockData& new_data); 38 | std::vector getWindowData() const; 39 | 40 | private: 41 | std::vector data_; 42 | std::deque sliding_window_; 43 | size_t window_size_; 44 | double mean_; // 添加均值存储 45 | double std_; // 添加标准差存储 46 | 47 | // 统计量计算 48 | double calculateMean(const std::vector& data) const; 49 | double calculateStd(const std::vector& data) const; 50 | 51 | // 数据验证 52 | bool isValidPrice(double price) const; 53 | bool isValidTimestamp(const boost::posix_time::ptime& timestamp) const; 54 | }; 55 | 56 | } // namespace stock_predictor -------------------------------------------------------------------------------- /C++面试急救包:20道必考算法题答案/m1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++面试急救包:20道必考算法题答案/m1.png -------------------------------------------------------------------------------- /C++面试急救包:20道必考算法题答案/m2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++面试急救包:20道必考算法题答案/m2.png -------------------------------------------------------------------------------- /C++面试急救包:20道必考算法题答案/m3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C++面试急救包:20道必考算法题答案/m3.png -------------------------------------------------------------------------------- /C语言实现简单Linux容器/container: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/C语言实现简单Linux容器/container -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(HsmmHttpServer VERSION 1.0.0 LANGUAGES CXX) 3 | 4 | # 设置C++标准 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | set(CMAKE_CXX_EXTENSIONS OFF) 8 | 9 | # 启用编译警告 10 | if(MSVC) 11 | add_compile_options(/W4) 12 | else() 13 | add_compile_options(-Wall -Wextra -Wpedantic) 14 | endif() 15 | 16 | # 启用Address Sanitizer (仅在Debug模式) 17 | if(CMAKE_BUILD_TYPE STREQUAL "Debug") 18 | add_compile_options(-fsanitize=address) 19 | add_link_options(-fsanitize=address) 20 | endif() 21 | 22 | # 查找Boost库 23 | find_package(Boost REQUIRED COMPONENTS system) 24 | 25 | # 设置可执行文件输出目录 26 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) 27 | 28 | # 源文件 29 | set(SERVER_SOURCES 30 | src/main.cpp 31 | src/server/Server.cpp 32 | src/server/Connection.cpp 33 | src/http/HttpParser.cpp 34 | ) 35 | 36 | # 主可执行文件 37 | add_executable(hsmmserver ${SERVER_SOURCES}) 38 | 39 | # 压力测试程序 40 | add_executable(stress_test src/test/stress_test.cpp) 41 | 42 | # 链接Boost库 43 | target_link_libraries(hsmmserver PRIVATE 44 | Boost::system 45 | pthread 46 | ) 47 | 48 | target_link_libraries(stress_test PRIVATE 49 | Boost::system 50 | pthread 51 | ) 52 | 53 | # 包含目录 54 | target_include_directories(hsmmserver PRIVATE 55 | ${CMAKE_SOURCE_DIR}/include 56 | ${Boost_INCLUDE_DIRS} 57 | ) 58 | 59 | target_include_directories(stress_test PRIVATE 60 | ${CMAKE_SOURCE_DIR}/include 61 | ${Boost_INCLUDE_DIRS} 62 | ) -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/README.md: -------------------------------------------------------------------------------- 1 | # HSMM HTTP Server 2 | 3 | 基于现代C++的高安全内存管理HTTP服务器 4 | 5 | ## 项目介绍 6 | 7 | HSMM HTTP Server是一个基于现代C++20开发的高性能HTTP服务器,专注于内存安全和高并发处理。该项目采用了最新的C++特性和最佳实践,提供了一个安全、高效、可扩展的HTTP服务器框架。 8 | 9 | ### 核心特性 10 | 11 | - **现代C++20特性** 12 | - 使用`std::span`进行安全的内存访问 13 | - 使用`std::string_view`实现零拷贝字符串处理 14 | - 支持协程和异步编程 15 | 16 | - **内存安全** 17 | - 多态内存资源(PMR)支持 18 | - RAII资源管理 19 | - 智能指针自动内存管理 20 | - 边界检查和缓冲区保护 21 | 22 | - **高性能设计** 23 | - 基于Boost.Asio的异步IO 24 | - 线程池并发处理 25 | - 零拷贝数据传输 26 | - 无锁队列日志系统 27 | 28 | - **可靠性保证** 29 | - 全面的错误处理 30 | - 异常安全 31 | - 资源自动回收 32 | - 超时保护机制 33 | 34 | ## 系统架构 35 | 36 | ### 核心组件 37 | 38 | 1. **Server类** (`include/server/Server.hpp`) 39 | - 服务器核心类,管理连接和线程池 40 | - 处理客户端连接请求 41 | - 维护工作线程池 42 | - 实现优雅关闭机制 43 | 44 | 2. **Connection类** (`include/server/Connection.hpp`) 45 | - 管理单个HTTP连接 46 | - 处理请求读取和响应发送 47 | - 实现HTTP协议解析 48 | - 支持keep-alive连接 49 | 50 | 3. **HttpParser类** (`include/http/HttpParser.hpp`) 51 | - HTTP请求解析器 52 | - 支持请求头和请求体解析 53 | - 处理HTTP方法、URI和头部字段 54 | - 提供响应生成功能 55 | 56 | 4. **SafeBuffer类** (`include/utils/SafeBuffer.hpp`) 57 | - 安全的缓冲区实现 58 | - 提供边界检查 59 | - 支持PMR内存分配 60 | - 自动内存管理 61 | 62 | 5. **Logger类** (`include/utils/Logger.hpp`) 63 | - 线程安全的日志系统 64 | - 支持多级别日志 65 | - 文件和控制台输出 66 | - 时间戳和格式化输出 67 | 68 | ## 构建要求 69 | 70 | - C++20兼容的编译器(GCC 10+, Clang 10+, MSVC 2019+) 71 | - CMake 3.15+ 72 | - Boost 1.74+ 73 | 74 | ## 构建步骤 75 | 76 | ```bash 77 | # 创建构建目录 78 | mkdir build && cd build 79 | 80 | # 配置项目 81 | cmake .. 82 | 83 | # 编译项目 84 | cmake --build . 85 | ``` 86 | 87 | ## 运行服务器 88 | 89 | ```bash 90 | # 使用默认配置运行(地址:0.0.0.0,端口:8080) 91 | ./bin/hsmmserver 92 | 93 | # 指定地址和端口运行 94 | ./bin/hsmmserver 127.0.0.1 8000 95 | 96 | # 指定地址、端口和线程数 97 | ./bin/hsmmserver 127.0.0.1 8000 4 98 | ``` 99 | 100 | ## 性能测试 101 | 102 | ### 压力测试工具 103 | 104 | 项目包含了一个专门的压力测试工具 `stress_test`,用于评估服务器的性能和稳定性。 105 | 106 | #### 使用方法 107 | 108 | ```bash 109 | ./bin/stress_test 110 | 111 | # 示例:发送1000个请求,使用10个并发连接 112 | ./bin/stress_test 127.0.0.1 8080 1000 10 113 | 114 | # 大规模测试:发送10000个请求,使用20个并发连接 115 | ./bin/stress_test 127.0.0.1 8080 10000 20 116 | ``` 117 | 118 | #### 参数说明 119 | - `host`: 服务器地址 120 | - `port`: 服务器端口 121 | - `total_requests`: 总请求数 122 | - `concurrent_connections`: 并发连接数 123 | 124 | #### 测试指标 125 | - 总请求数和成功率 126 | - 每秒查询数(QPS) 127 | - 平均响应延迟 128 | - 错误请求数量 129 | - 总测试时间 130 | 131 | ### 测试结果示例 132 | 133 | 在本地测试环境下(MacBook Pro),服务器表现: 134 | 135 | 1. 小规模测试(1000请求,10并发): 136 | - QPS: ~5300 137 | - 平均延迟: ~1.25ms 138 | - 成功率: 100% 139 | 140 | 2. 中等规模测试(10000请求,20并发): 141 | - QPS: ~8000 142 | - 平均延迟: ~1.96ms 143 | - 成功率: 100% 144 | 145 | ## API接口 146 | 147 | ### HTTP请求处理 148 | 149 | 服务器支持标准的HTTP/1.1协议,当前实现的接口包括: 150 | 151 | 1. **GET 请求** 152 | - 路径: `/` 153 | - 响应: 纯文本消息 154 | - 示例响应: 155 | ``` 156 | HTTP/1.1 200 OK 157 | Content-Length: 28 158 | Server: HSMM-HTTP-Server 159 | Content-Type: text/plain 160 | 161 | Hello from HSMM HTTP Server! 162 | ``` 163 | 164 | 2. **错误处理** 165 | - 400 Bad Request: 请求格式错误 166 | - 404 Not Found: 资源不存在 167 | - 500 Internal Server Error: 服务器内部错误 168 | 169 | ## 安全特性 170 | 171 | - 使用`std::unique_ptr`和`std::shared_ptr`进行自动内存管理 172 | - 使用`std::span`进行安全的缓冲区访问 173 | - 使用`std::string_view`实现零拷贝字符串处理 174 | - PMR内存池减少内存碎片 175 | - RAII确保资源正确释放 176 | - 支持AddressSanitizer进行运行时检测 177 | 178 | ## 许可证 179 | 180 | MIT License -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/3.31.6/CMakeDetermineCompilerABI_CXX.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/Hsmm-HTTP-Server/build/CMakeFiles/3.31.6/CMakeDetermineCompilerABI_CXX.bin -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/3.31.6/CMakeSystem.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_HOST_SYSTEM "Darwin-23.2.0") 2 | set(CMAKE_HOST_SYSTEM_NAME "Darwin") 3 | set(CMAKE_HOST_SYSTEM_VERSION "23.2.0") 4 | set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") 5 | 6 | 7 | 8 | set(CMAKE_SYSTEM "Darwin-23.2.0") 9 | set(CMAKE_SYSTEM_NAME "Darwin") 10 | set(CMAKE_SYSTEM_VERSION "23.2.0") 11 | set(CMAKE_SYSTEM_PROCESSOR "x86_64") 12 | 13 | set(CMAKE_CROSSCOMPILING "FALSE") 14 | 15 | set(CMAKE_SYSTEM_LOADED 1) 16 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/3.31.6/CompilerIdCXX/CMakeCXXCompilerId.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/Hsmm-HTTP-Server/build/CMakeFiles/3.31.6/CompilerIdCXX/CMakeCXXCompilerId.o -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/CMakeDirectoryInformation.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.31 3 | 4 | # Relative path conversion top directories. 5 | set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server") 6 | set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/build") 7 | 8 | # Force unix paths in dependencies. 9 | set(CMAKE_FORCE_UNIX_PATHS 1) 10 | 11 | 12 | # The C and CXX include file regular expressions for this directory. 13 | set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") 14 | set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") 15 | set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) 16 | set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) 17 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/TargetDirectories.txt: -------------------------------------------------------------------------------- 1 | /Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir 2 | /Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir 3 | /Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/build/CMakeFiles/edit_cache.dir 4 | /Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/build/CMakeFiles/rebuild_cache.dir 5 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/cmake.check_cache: -------------------------------------------------------------------------------- 1 | # This file is generated by cmake for dependency checking of the CMakeCache.txt file 2 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Consider dependencies only in project. 3 | set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) 4 | 5 | # The set of languages for which implicit dependencies are needed: 6 | set(CMAKE_DEPENDS_LANGUAGES 7 | ) 8 | 9 | # The set of dependency files which are needed: 10 | set(CMAKE_DEPENDS_DEPENDENCY_FILES 11 | "/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/src/http/HttpParser.cpp" "CMakeFiles/hsmmserver.dir/src/http/HttpParser.cpp.o" "gcc" "CMakeFiles/hsmmserver.dir/src/http/HttpParser.cpp.o.d" 12 | "/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/src/main.cpp" "CMakeFiles/hsmmserver.dir/src/main.cpp.o" "gcc" "CMakeFiles/hsmmserver.dir/src/main.cpp.o.d" 13 | "/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/src/server/Connection.cpp" "CMakeFiles/hsmmserver.dir/src/server/Connection.cpp.o" "gcc" "CMakeFiles/hsmmserver.dir/src/server/Connection.cpp.o.d" 14 | "/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/src/server/Server.cpp" "CMakeFiles/hsmmserver.dir/src/server/Server.cpp.o" "gcc" "CMakeFiles/hsmmserver.dir/src/server/Server.cpp.o.d" 15 | ) 16 | 17 | # Targets to which this target links which contain Fortran sources. 18 | set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES 19 | ) 20 | 21 | # Targets to which this target links which contain Fortran sources. 22 | set(CMAKE_Fortran_TARGET_FORWARD_LINKED_INFO_FILES 23 | ) 24 | 25 | # Fortran module output directory. 26 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 27 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/hsmmserver.dir/src/http/HttpParser.cpp.o" 3 | "CMakeFiles/hsmmserver.dir/src/http/HttpParser.cpp.o.d" 4 | "CMakeFiles/hsmmserver.dir/src/main.cpp.o" 5 | "CMakeFiles/hsmmserver.dir/src/main.cpp.o.d" 6 | "CMakeFiles/hsmmserver.dir/src/server/Connection.cpp.o" 7 | "CMakeFiles/hsmmserver.dir/src/server/Connection.cpp.o.d" 8 | "CMakeFiles/hsmmserver.dir/src/server/Server.cpp.o" 9 | "CMakeFiles/hsmmserver.dir/src/server/Server.cpp.o.d" 10 | "bin/hsmmserver" 11 | "bin/hsmmserver.pdb" 12 | ) 13 | 14 | # Per-language clean rules from dependency scanning. 15 | foreach(lang CXX) 16 | include(CMakeFiles/hsmmserver.dir/cmake_clean_${lang}.cmake OPTIONAL) 17 | endforeach() 18 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/compiler_depend.ts: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Timestamp file for compiler generated dependencies management for hsmmserver. 3 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/depend.make: -------------------------------------------------------------------------------- 1 | # Empty dependencies file for hsmmserver. 2 | # This may be replaced when dependencies are built. 3 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.31 3 | 4 | # compile CXX with /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ 5 | CXX_DEFINES = -DBOOST_SYSTEM_DYN_LINK -DBOOST_SYSTEM_NO_LIB 6 | 7 | CXX_INCLUDES = -I/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/include -isystem /opt/anaconda3/include 8 | 9 | CXX_FLAGS = -std=c++20 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 -Wall -Wextra -Wpedantic 10 | 11 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/link.txt: -------------------------------------------------------------------------------- 1 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/hsmmserver.dir/src/main.cpp.o CMakeFiles/hsmmserver.dir/src/server/Server.cpp.o CMakeFiles/hsmmserver.dir/src/server/Connection.cpp.o CMakeFiles/hsmmserver.dir/src/http/HttpParser.cpp.o -o bin/hsmmserver -Wl,-rpath,/opt/anaconda3/lib /opt/anaconda3/lib/libboost_system.dylib -lpthread 2 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 1 2 | CMAKE_PROGRESS_2 = 2 3 | CMAKE_PROGRESS_3 = 3 4 | CMAKE_PROGRESS_4 = 4 5 | CMAKE_PROGRESS_5 = 5 6 | 7 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/src/http/HttpParser.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/src/http/HttpParser.cpp.o -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/src/main.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/src/main.cpp.o -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/src/server/Connection.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/src/server/Connection.cpp.o -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/src/server/Server.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/Hsmm-HTTP-Server/build/CMakeFiles/hsmmserver.dir/src/server/Server.cpp.o -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/progress.marks: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Consider dependencies only in project. 3 | set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) 4 | 5 | # The set of languages for which implicit dependencies are needed: 6 | set(CMAKE_DEPENDS_LANGUAGES 7 | ) 8 | 9 | # The set of dependency files which are needed: 10 | set(CMAKE_DEPENDS_DEPENDENCY_FILES 11 | "/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/src/test/stress_test.cpp" "CMakeFiles/stress_test.dir/src/test/stress_test.cpp.o" "gcc" "CMakeFiles/stress_test.dir/src/test/stress_test.cpp.o.d" 12 | ) 13 | 14 | # Targets to which this target links which contain Fortran sources. 15 | set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES 16 | ) 17 | 18 | # Targets to which this target links which contain Fortran sources. 19 | set(CMAKE_Fortran_TARGET_FORWARD_LINKED_INFO_FILES 20 | ) 21 | 22 | # Fortran module output directory. 23 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 24 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/stress_test.dir/src/test/stress_test.cpp.o" 3 | "CMakeFiles/stress_test.dir/src/test/stress_test.cpp.o.d" 4 | "bin/stress_test" 5 | "bin/stress_test.pdb" 6 | ) 7 | 8 | # Per-language clean rules from dependency scanning. 9 | foreach(lang CXX) 10 | include(CMakeFiles/stress_test.dir/cmake_clean_${lang}.cmake OPTIONAL) 11 | endforeach() 12 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir/compiler_depend.ts: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Timestamp file for compiler generated dependencies management for stress_test. 3 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir/depend.make: -------------------------------------------------------------------------------- 1 | # Empty dependencies file for stress_test. 2 | # This may be replaced when dependencies are built. 3 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.31 3 | 4 | # compile CXX with /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ 5 | CXX_DEFINES = -DBOOST_SYSTEM_DYN_LINK -DBOOST_SYSTEM_NO_LIB 6 | 7 | CXX_INCLUDES = -I/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/include -isystem /opt/anaconda3/include 8 | 9 | CXX_FLAGS = -std=c++20 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 -Wall -Wextra -Wpedantic 10 | 11 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir/link.txt: -------------------------------------------------------------------------------- 1 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/stress_test.dir/src/test/stress_test.cpp.o -o bin/stress_test -Wl,-rpath,/opt/anaconda3/lib /opt/anaconda3/lib/libboost_system.dylib -lpthread 2 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 6 2 | CMAKE_PROGRESS_2 = 7 3 | 4 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir/src/test/stress_test.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/Hsmm-HTTP-Server/build/CMakeFiles/stress_test.dir/src/test/stress_test.cpp.o -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/bin/hsmmserver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/Hsmm-HTTP-Server/build/bin/hsmmserver -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/bin/stress_test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/Hsmm-HTTP-Server/build/bin/stress_test -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/build/cmake_install.cmake: -------------------------------------------------------------------------------- 1 | # Install script for directory: /Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server 2 | 3 | # Set the install prefix 4 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 5 | set(CMAKE_INSTALL_PREFIX "/usr/local/Homebrew") 6 | endif() 7 | string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 8 | 9 | # Set the install configuration name. 10 | if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) 11 | if(BUILD_TYPE) 12 | string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" 13 | CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") 14 | else() 15 | set(CMAKE_INSTALL_CONFIG_NAME "") 16 | endif() 17 | message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") 18 | endif() 19 | 20 | # Set the component getting installed. 21 | if(NOT CMAKE_INSTALL_COMPONENT) 22 | if(COMPONENT) 23 | message(STATUS "Install component: \"${COMPONENT}\"") 24 | set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") 25 | else() 26 | set(CMAKE_INSTALL_COMPONENT) 27 | endif() 28 | endif() 29 | 30 | # Is this installation the result of a crosscompile? 31 | if(NOT DEFINED CMAKE_CROSSCOMPILING) 32 | set(CMAKE_CROSSCOMPILING "FALSE") 33 | endif() 34 | 35 | # Set path to fallback-tool for dependency-resolution. 36 | if(NOT DEFINED CMAKE_OBJDUMP) 37 | set(CMAKE_OBJDUMP "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/objdump") 38 | endif() 39 | 40 | string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT 41 | "${CMAKE_INSTALL_MANIFEST_FILES}") 42 | if(CMAKE_INSTALL_LOCAL_ONLY) 43 | file(WRITE "/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/build/install_local_manifest.txt" 44 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 45 | endif() 46 | if(CMAKE_INSTALL_COMPONENT) 47 | if(CMAKE_INSTALL_COMPONENT MATCHES "^[a-zA-Z0-9_.+-]+$") 48 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") 49 | else() 50 | string(MD5 CMAKE_INST_COMP_HASH "${CMAKE_INSTALL_COMPONENT}") 51 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INST_COMP_HASH}.txt") 52 | unset(CMAKE_INST_COMP_HASH) 53 | endif() 54 | else() 55 | set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") 56 | endif() 57 | 58 | if(NOT CMAKE_INSTALL_LOCAL_ONLY) 59 | file(WRITE "/Users/zhulei/Downloads/trae_project/Hsmm-HTTP-Server/build/${CMAKE_INSTALL_MANIFEST}" 60 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 61 | endif() 62 | -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/include/http/HttpParser.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace hsmm { 9 | namespace http { 10 | 11 | /** 12 | * @brief HTTP请求解析结果 13 | */ 14 | struct HttpRequest { 15 | std::string_view method; 16 | std::string_view uri; 17 | std::string_view version; 18 | std::unordered_map headers; 19 | std::string_view body; 20 | }; 21 | 22 | /** 23 | * @brief HTTP响应生成器 24 | */ 25 | class HttpResponse { 26 | public: 27 | /** 28 | * @brief 设置状态码和状态消息 29 | * @param code HTTP状态码 30 | * @param message 状态消息 31 | */ 32 | void set_status(int code, std::string_view message); 33 | 34 | /** 35 | * @brief 添加响应头 36 | * @param name 头部字段名 37 | * @param value 头部字段值 38 | */ 39 | void add_header(std::string_view name, std::string_view value); 40 | 41 | /** 42 | * @brief 设置响应体 43 | * @param body 响应体内容 44 | */ 45 | void set_body(std::string_view body); 46 | 47 | /** 48 | * @brief 生成完整的HTTP响应 49 | * @return 格式化后的HTTP响应字符串 50 | */ 51 | std::string to_string() const; 52 | 53 | private: 54 | int status_code_{200}; 55 | std::string_view status_message_{"OK"}; 56 | std::unordered_map headers_; 57 | std::string_view body_; 58 | }; 59 | 60 | /** 61 | * @brief HTTP请求解析器 62 | */ 63 | class HttpParser { 64 | public: 65 | /** 66 | * @brief 解析HTTP请求 67 | * @param data 请求数据 68 | * @return 解析结果,如果解析失败返回std::nullopt 69 | */ 70 | static std::optional parse(std::span data); 71 | 72 | private: 73 | /** 74 | * @brief 解析请求行 75 | * @param line 请求行数据 76 | * @param request 解析结果存储对象 77 | * @return 是否解析成功 78 | */ 79 | static bool parse_request_line(std::string_view line, HttpRequest& request); 80 | 81 | /** 82 | * @brief 解析头部字段 83 | * @param line 头部字段行 84 | * @param request 解析结果存储对象 85 | * @return 是否解析成功 86 | */ 87 | static bool parse_header(std::string_view line, HttpRequest& request); 88 | }; 89 | 90 | } // namespace http 91 | } // namespace hsmm -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/include/server/Connection.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace hsmm { 10 | 11 | /** 12 | * @brief HTTP连接类 13 | * 14 | * 使用RAII管理单个HTTP连接的生命周期 15 | */ 16 | class Connection : public std::enable_shared_from_this { 17 | public: 18 | /** 19 | * @brief 构造函数 20 | * @param socket 已接受的TCP socket 21 | */ 22 | explicit Connection(boost::asio::ip::tcp::socket socket); 23 | 24 | /** 25 | * @brief 开始处理连接 26 | */ 27 | void start(); 28 | 29 | private: 30 | /** 31 | * @brief 异步读取HTTP请求 32 | */ 33 | void do_read(); 34 | 35 | /** 36 | * @brief 异步发送HTTP响应 37 | * @param response 要发送的响应数据 38 | */ 39 | void do_write(std::string_view response); 40 | 41 | /** 42 | * @brief 解析HTTP请求 43 | * @param data 接收到的数据 44 | * @param length 数据长度 45 | * @return 是否解析成功 46 | */ 47 | bool parse_request(std::span data); 48 | 49 | private: 50 | boost::asio::ip::tcp::socket socket_; 51 | 52 | // 使用固定大小的缓冲区,防止缓冲区溢出 53 | static constexpr size_t max_buffer_size = 8192; 54 | std::array buffer_; 55 | 56 | // 请求解析结果 57 | std::string_view method_; 58 | std::string_view uri_; 59 | std::string_view version_; 60 | }; 61 | 62 | } // namespace hsmm -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/include/server/Server.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace hsmm { 12 | 13 | /** 14 | * @brief HTTP服务器核心类 15 | * 16 | * 使用RAII管理资源生命周期,实现内存安全的HTTP服务器 17 | */ 18 | class Server { 19 | public: 20 | /** 21 | * @brief 构造函数 22 | * @param address 服务器监听地址 23 | * @param port 服务器监听端口 24 | * @param thread_count 工作线程数量 25 | */ 26 | Server(const std::string& address, unsigned short port, size_t thread_count = std::thread::hardware_concurrency()); 27 | 28 | /** 29 | * @brief 启动服务器 30 | * @throws boost::system::system_error 如果启动失败 31 | */ 32 | void run(); 33 | 34 | /** 35 | * @brief 停止服务器 36 | */ 37 | void stop(); 38 | 39 | private: 40 | /** 41 | * @brief 接受新的连接 42 | */ 43 | void do_accept(); 44 | 45 | /** 46 | * @brief 工作线程函数 47 | */ 48 | void worker_thread(); 49 | 50 | private: 51 | boost::asio::io_context io_context_; 52 | boost::asio::executor_work_guard work_guard_; 53 | boost::asio::ip::tcp::acceptor acceptor_; 54 | std::vector worker_threads_; 55 | 56 | // 使用PMR内存池管理连接对象 57 | std::pmr::synchronized_pool_resource connection_pool_; 58 | 59 | // 服务器配置 60 | const size_t thread_count_; 61 | std::atomic running_{false}; 62 | }; 63 | 64 | } // namespace hsmm -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/include/utils/Logger.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | namespace hsmm { 14 | namespace utils { 15 | 16 | /** 17 | * @brief 日志级别枚举 18 | */ 19 | enum class LogLevel { 20 | DEBUG, 21 | INFO, 22 | WARNING, 23 | ERROR 24 | }; 25 | 26 | /** 27 | * @brief 线程安全的日志类 28 | */ 29 | class Logger { 30 | public: 31 | /** 32 | * @brief 获取日志单例实例 33 | * @return Logger实例的引用 34 | */ 35 | static Logger& instance() { 36 | static Logger instance; 37 | return instance; 38 | } 39 | 40 | /** 41 | * @brief 初始化日志系统 42 | * @param filename 日志文件名 43 | * @param level 最低日志级别 44 | */ 45 | void init(const std::string& filename, LogLevel level = LogLevel::INFO) { 46 | std::lock_guard lock(mutex_); 47 | file_.open(filename, std::ios::app); 48 | level_ = level; 49 | } 50 | 51 | /** 52 | * @brief 写入日志 53 | * @param level 日志级别 54 | * @param message 日志消息 55 | */ 56 | void log(LogLevel level, std::string_view message) { 57 | if (level < level_) return; 58 | 59 | std::lock_guard lock(mutex_); 60 | 61 | auto now = std::chrono::system_clock::now(); 62 | auto time = std::chrono::system_clock::to_time_t(now); 63 | 64 | std::stringstream ss; 65 | ss << "[" << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S") << "] " 66 | << level_to_string(level) << ": " 67 | << message << std::endl; 68 | 69 | if (file_.is_open()) { 70 | file_ << ss.str(); 71 | file_.flush(); 72 | } 73 | 74 | // 同时输出到控制台 75 | std::cout << ss.str(); 76 | } 77 | 78 | // 便捷日志方法 79 | void debug(std::string_view message) { log(LogLevel::DEBUG, message); } 80 | void info(std::string_view message) { log(LogLevel::INFO, message); } 81 | void warning(std::string_view message) { log(LogLevel::WARNING, message); } 82 | void error(std::string_view message) { log(LogLevel::ERROR, message); } 83 | 84 | private: 85 | Logger() = default; 86 | ~Logger() { 87 | if (file_.is_open()) { 88 | file_.close(); 89 | } 90 | } 91 | 92 | // 禁止拷贝和移动 93 | Logger(const Logger&) = delete; 94 | Logger& operator=(const Logger&) = delete; 95 | Logger(Logger&&) = delete; 96 | Logger& operator=(Logger&&) = delete; 97 | 98 | /** 99 | * @brief 将日志级别转换为字符串 100 | * @param level 日志级别 101 | * @return 对应的字符串表示 102 | */ 103 | static std::string_view level_to_string(LogLevel level) { 104 | switch (level) { 105 | case LogLevel::DEBUG: return "DEBUG"; 106 | case LogLevel::INFO: return "INFO"; 107 | case LogLevel::WARNING: return "WARNING"; 108 | case LogLevel::ERROR: return "ERROR"; 109 | default: return "UNKNOWN"; 110 | } 111 | } 112 | 113 | private: 114 | std::mutex mutex_; 115 | std::ofstream file_; 116 | LogLevel level_{LogLevel::INFO}; 117 | }; 118 | 119 | } // namespace utils 120 | } // namespace hsmm 121 | 122 | // 便捷宏定义 123 | #define LOG_DEBUG(msg) hsmm::utils::Logger::instance().debug(msg) 124 | #define LOG_INFO(msg) hsmm::utils::Logger::instance().info(msg) 125 | #define LOG_WARNING(msg) hsmm::utils::Logger::instance().warning(msg) 126 | #define LOG_ERROR(msg) hsmm::utils::Logger::instance().error(msg) -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/include/utils/SafeBuffer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace hsmm { 10 | namespace utils { 11 | 12 | /** 13 | * @brief 安全的缓冲区类 14 | * 15 | * 提供边界检查和自动内存管理的缓冲区实现 16 | * @tparam T 缓冲区元素类型 17 | */ 18 | template 19 | class SafeBuffer { 20 | public: 21 | /** 22 | * @brief 构造函数 23 | * @param size 缓冲区大小 24 | * @param resource 内存分配器 25 | */ 26 | explicit SafeBuffer(size_t size, 27 | std::pmr::memory_resource* resource = std::pmr::get_default_resource()) 28 | : data_(std::pmr::polymorphic_allocator(resource)) { 29 | data_.resize(size); 30 | } 31 | 32 | /** 33 | * @brief 获取只读视图 34 | * @return 缓冲区的只读span 35 | */ 36 | std::span view() const noexcept { 37 | return std::span(data_); 38 | } 39 | 40 | /** 41 | * @brief 获取可写视图 42 | * @return 缓冲区的可写span 43 | */ 44 | std::span view() noexcept { 45 | return std::span(data_); 46 | } 47 | 48 | /** 49 | * @brief 安全的写入操作 50 | * @param pos 写入位置 51 | * @param value 要写入的值 52 | * @throws std::out_of_range 如果位置越界 53 | */ 54 | void write(size_t pos, const T& value) { 55 | if (pos >= data_.size()) { 56 | throw std::out_of_range("Buffer write position out of range"); 57 | } 58 | data_[pos] = value; 59 | } 60 | 61 | /** 62 | * @brief 安全的读取操作 63 | * @param pos 读取位置 64 | * @return 读取的值 65 | * @throws std::out_of_range 如果位置越界 66 | */ 67 | const T& read(size_t pos) const { 68 | if (pos >= data_.size()) { 69 | throw std::out_of_range("Buffer read position out of range"); 70 | } 71 | return data_[pos]; 72 | } 73 | 74 | /** 75 | * @brief 获取缓冲区大小 76 | * @return 缓冲区大小 77 | */ 78 | size_t size() const noexcept { 79 | return data_.size(); 80 | } 81 | 82 | /** 83 | * @brief 清空缓冲区 84 | */ 85 | void clear() noexcept { 86 | data_.clear(); 87 | } 88 | 89 | /** 90 | * @brief 重置缓冲区大小 91 | * @param new_size 新的缓冲区大小 92 | */ 93 | void resize(size_t new_size) { 94 | data_.resize(new_size); 95 | } 96 | 97 | private: 98 | std::pmr::vector data_; 99 | }; 100 | 101 | } // namespace utils 102 | } // namespace hsmm -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "server/Server.hpp" 2 | #include "utils/Logger.hpp" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace { 10 | std::unique_ptr server; 11 | 12 | void signal_handler(int signal) { 13 | if (server) { 14 | std::cout << "\n正在关闭服务器..." << std::endl; 15 | server->stop(); 16 | } 17 | } 18 | } 19 | 20 | int main(int argc, char* argv[]) { 21 | try { 22 | // 初始化日志系统 23 | auto log_dir = std::filesystem::current_path() / "logs"; 24 | std::filesystem::create_directories(log_dir); 25 | hsmm::utils::Logger::instance().init((log_dir / "server.log").string()); 26 | 27 | LOG_INFO("正在启动服务器..."); 28 | 29 | // 设置信号处理 30 | std::signal(SIGINT, signal_handler); 31 | std::signal(SIGTERM, signal_handler); 32 | 33 | // 默认配置 34 | const char* address = "0.0.0.0"; 35 | unsigned short port = 8080; 36 | size_t thread_count = std::thread::hardware_concurrency(); 37 | 38 | // 解析命令行参数 39 | if (argc > 1) address = argv[1]; 40 | if (argc > 2) port = static_cast(std::atoi(argv[2])); 41 | if (argc > 3) thread_count = static_cast(std::atoi(argv[3])); 42 | 43 | // 创建并启动服务器 44 | LOG_INFO("配置信息:"); 45 | LOG_INFO(" - 监听地址: " + std::string(address)); 46 | LOG_INFO(" - 端口: " + std::to_string(port)); 47 | LOG_INFO(" - 线程数: " + std::to_string(thread_count)); 48 | 49 | server = std::make_unique(address, port, thread_count); 50 | 51 | LOG_INFO("服务器创建成功,开始运行..."); 52 | server->run(); 53 | 54 | return 0; 55 | } 56 | catch (const std::exception& e) { 57 | LOG_ERROR("服务器启动失败: " + std::string(e.what())); 58 | std::cerr << "错误: " << e.what() << std::endl; 59 | return 1; 60 | } 61 | } -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/src/server/Connection.cpp: -------------------------------------------------------------------------------- 1 | #include "server/Connection.hpp" 2 | #include "http/HttpParser.hpp" 3 | #include "utils/Logger.hpp" 4 | #include 5 | #include 6 | #include 7 | 8 | namespace hsmm { 9 | 10 | Connection::Connection(boost::asio::ip::tcp::socket socket) 11 | : socket_(std::move(socket)) { 12 | } 13 | 14 | void Connection::start() { 15 | do_read(); 16 | } 17 | 18 | void Connection::do_read() { 19 | auto self(shared_from_this()); 20 | 21 | socket_.async_read_some( 22 | boost::asio::buffer(buffer_), 23 | [this, self](boost::system::error_code ec, std::size_t length) { 24 | if (!ec) { 25 | // 解析HTTP请求 26 | if (auto request = http::HttpParser::parse(std::span(buffer_.data(), length))) { 27 | // 创建响应 28 | http::HttpResponse response; 29 | response.set_status(200, "OK"); 30 | response.add_header("Content-Type", "text/plain"); 31 | response.add_header("Server", "HSMM-HTTP-Server"); 32 | response.set_body("Hello from HSMM HTTP Server!"); 33 | 34 | // 发送响应 35 | do_write(response.to_string()); 36 | } else { 37 | // 请求解析失败 38 | http::HttpResponse response; 39 | response.set_status(400, "Bad Request"); 40 | response.add_header("Content-Type", "text/plain"); 41 | response.set_body("Invalid HTTP request"); 42 | 43 | do_write(response.to_string()); 44 | } 45 | } else if (ec != boost::asio::error::operation_aborted) { 46 | LOG_ERROR("读取连接数据失败: " + std::string(ec.message())); 47 | } 48 | }); 49 | } 50 | 51 | void Connection::do_write(std::string_view response) { 52 | auto self(shared_from_this()); 53 | 54 | boost::asio::async_write( 55 | socket_, 56 | boost::asio::buffer(response.data(), response.size()), 57 | [this, self](boost::system::error_code ec, std::size_t /*length*/) { 58 | if (!ec) { 59 | // 继续读取下一个请求 60 | do_read(); 61 | } else if (ec != boost::asio::error::operation_aborted) { 62 | LOG_ERROR("写入响应数据失败: " + std::string(ec.message())); 63 | } 64 | }); 65 | } 66 | 67 | bool Connection::parse_request(std::span data) { 68 | // 使用HttpParser解析请求 69 | auto request = http::HttpParser::parse(data); 70 | if (!request) { 71 | return false; 72 | } 73 | 74 | method_ = request->method; 75 | uri_ = request->uri; 76 | version_ = request->version; 77 | 78 | return true; 79 | } 80 | } -------------------------------------------------------------------------------- /Hsmm-HTTP-Server/src/server/Server.cpp: -------------------------------------------------------------------------------- 1 | #include "server/Server.hpp" 2 | #include "server/Connection.hpp" 3 | #include "utils/Logger.hpp" 4 | #include 5 | #include 6 | #include 7 | 8 | namespace hsmm { 9 | 10 | Server::Server(const std::string& address, unsigned short port, size_t thread_count) 11 | : io_context_(thread_count) // 设置并发线程数 12 | , work_guard_(boost::asio::make_work_guard(io_context_)) // 防止io_context过早退出 13 | , acceptor_(io_context_) 14 | , thread_count_(thread_count) { 15 | 16 | boost::asio::ip::tcp::endpoint endpoint( 17 | boost::asio::ip::make_address(address), port); 18 | 19 | // 配置接受器 20 | boost::system::error_code ec; 21 | acceptor_.open(endpoint.protocol(), ec); 22 | if (ec) { 23 | LOG_ERROR("打开接受器失败: " + ec.message()); 24 | throw std::runtime_error("打开接受器失败: " + ec.message()); 25 | } 26 | 27 | acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), ec); 28 | if (ec) { 29 | LOG_ERROR("设置地址重用选项失败: " + ec.message()); 30 | throw std::runtime_error("设置地址重用选项失败: " + ec.message()); 31 | } 32 | 33 | acceptor_.bind(endpoint, ec); 34 | if (ec) { 35 | LOG_ERROR("绑定地址失败: " + ec.message()); 36 | throw std::runtime_error("绑定地址失败: " + ec.message()); 37 | } 38 | 39 | acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec); 40 | if (ec) { 41 | LOG_ERROR("开始监听失败: " + ec.message()); 42 | throw std::runtime_error("开始监听失败: " + ec.message()); 43 | } 44 | 45 | LOG_INFO("服务器初始化完成,监听地址: " + address + ":" + std::to_string(port)); 46 | } 47 | 48 | void Server::run() { 49 | running_ = true; 50 | 51 | // 启动工作线程 52 | LOG_INFO("启动工作线程池,线程数: " + std::to_string(thread_count_)); 53 | for (size_t i = 0; i < thread_count_ - 1; ++i) { 54 | worker_threads_.emplace_back([this] { worker_thread(); }); 55 | } 56 | 57 | // 启动接受连接 58 | do_accept(); 59 | 60 | // 主线程也运行io_context 61 | try { 62 | io_context_.run(); 63 | LOG_INFO("服务器主循环退出"); 64 | } 65 | catch (const std::exception& e) { 66 | LOG_ERROR("主线程异常: " + std::string(e.what())); 67 | stop(); 68 | } 69 | } 70 | 71 | void Server::stop() { 72 | if (!running_) return; 73 | 74 | LOG_INFO("正在停止服务器..."); 75 | running_ = false; 76 | 77 | // 停止接受新的工作 78 | work_guard_.reset(); 79 | 80 | // 停止io_context 81 | io_context_.stop(); 82 | 83 | // 等待所有工作线程结束 84 | for (auto& thread : worker_threads_) { 85 | if (thread.joinable()) { 86 | thread.join(); 87 | } 88 | } 89 | 90 | LOG_INFO("服务器已停止"); 91 | } 92 | 93 | void Server::do_accept() { 94 | if (!running_) return; 95 | 96 | acceptor_.async_accept( 97 | [this](boost::system::error_code ec, boost::asio::ip::tcp::socket socket) { 98 | if (!ec) { 99 | try { 100 | LOG_DEBUG("接受新连接: " + socket.remote_endpoint().address().to_string() + 101 | ":" + std::to_string(socket.remote_endpoint().port())); 102 | 103 | // 使用PMR内存池创建连接对象 104 | auto connection = std::allocate_shared( 105 | std::pmr::polymorphic_allocator(&connection_pool_), 106 | std::move(socket)); 107 | 108 | connection->start(); 109 | } 110 | catch (const std::exception& e) { 111 | LOG_ERROR("处理新连接时发生错误: " + std::string(e.what())); 112 | } 113 | } else { 114 | LOG_ERROR("接受连接失败: " + ec.message()); 115 | } 116 | 117 | // 继续接受下一个连接 118 | if (running_) { 119 | do_accept(); 120 | } 121 | }); 122 | } 123 | 124 | void Server::worker_thread() { 125 | try { 126 | io_context_.run(); 127 | LOG_INFO("工作线程退出"); 128 | } 129 | catch (const std::exception& e) { 130 | LOG_ERROR("工作线程异常: " + std::string(e.what())); 131 | } 132 | } 133 | } -------------------------------------------------------------------------------- /memalloc/README.md: -------------------------------------------------------------------------------- 1 | ### memalloc 2 | memalloc是一个简单的内存分配器。 3 | 4 | 它实现了`malloc()`、`calloc()`、`realloc()`和`free()`函数。 5 | 6 | - **编译与运行**:使用`gcc -o memalloc.so -fPIC -shared memalloc.c`命令进行编译。其中,`-fPIC`和`-shared`选项确保编译输出的是位置无关代码,并指示链接器生成适合动态链接的共享对象。 7 | 8 | 在Linux系统上,如果将环境变量`LD_PRELOAD`设置为共享对象的路径,那么该文件将在其他任何库之前被加载。我们可以利用这个技巧先加载编译好的库文件,这样在 shell 中后续运行的命令就会使用我们的`malloc()`、`free()`、`calloc()`和`realloc()`函数。 9 | 10 | 执行`export LD_PRELOAD=$PWD/memalloc.so`命令。此时,如果你运行诸如`ls`的命令,它将使用我们的内存分配器。 11 | ```bash 12 | ls 13 | memalloc.c memalloc.so README.md 14 | ``` 15 | 或者运行`vim memalloc.c`命令。你也可以使用这个内存分配器来运行自己的程序。 16 | 17 | 一旦你完成实验,可以执行`unset LD_PRELOAD`命令停止使用我们的分配器。 -------------------------------------------------------------------------------- /movie_recommender/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(MovieRecommender) 3 | 4 | set(CMAKE_CXX_STANDARD 17) 5 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 6 | 7 | # 查找SQLite3 8 | find_package(SQLite3 REQUIRED) 9 | 10 | # 添加源文件 11 | set(SOURCES 12 | main.cpp 13 | MovieRecommender.cpp 14 | Database.cpp 15 | SVD.cpp 16 | ) 17 | 18 | # 添加头文件 19 | set(HEADERS 20 | MovieRecommender.h 21 | Database.h 22 | SVD.h 23 | ) 24 | 25 | # 创建可执行文件 26 | add_executable(movie_recommender ${SOURCES} ${HEADERS}) 27 | 28 | # 链接SQLite3 29 | target_link_libraries(movie_recommender PRIVATE SQLite::SQLite3) 30 | 31 | # 添加编译选项 32 | if(MSVC) 33 | target_compile_options(movie_recommender PRIVATE /W4) 34 | else() 35 | target_compile_options(movie_recommender PRIVATE -Wall -Wextra -Wpedantic) 36 | endif() -------------------------------------------------------------------------------- /movie_recommender/Database.cpp: -------------------------------------------------------------------------------- 1 | #include "Database.h" 2 | #include 3 | #include 4 | 5 | Database::Database(const std::string& dbPath) : dbPath_(dbPath), db_(nullptr) { 6 | initialize(); 7 | } 8 | 9 | Database::~Database() { 10 | if (db_) { 11 | sqlite3_close(db_); 12 | } 13 | } 14 | 15 | void Database::initialize() { 16 | int rc = sqlite3_open(dbPath_.c_str(), &db_); 17 | if (rc) { 18 | throw std::runtime_error("无法打开数据库: " + std::string(sqlite3_errmsg(db_))); 19 | } 20 | createTables(); 21 | } 22 | 23 | void Database::createTables() { 24 | const char* sql = 25 | "CREATE TABLE IF NOT EXISTS ratings (" 26 | "user_id INTEGER NOT NULL," 27 | "movie_id INTEGER NOT NULL," 28 | "rating REAL NOT NULL," 29 | "PRIMARY KEY (user_id, movie_id));"; 30 | 31 | executeQuery(sql); 32 | } 33 | 34 | void Database::executeQuery(const std::string& sql) { 35 | char* errMsg = nullptr; 36 | int rc = sqlite3_exec(db_, sql.c_str(), nullptr, nullptr, &errMsg); 37 | 38 | if (rc != SQLITE_OK) { 39 | std::string error = errMsg; 40 | sqlite3_free(errMsg); 41 | throw std::runtime_error("SQL错误: " + error); 42 | } 43 | } 44 | 45 | void Database::addRating(int userId, int movieId, double rating) { 46 | std::string sql = "INSERT OR REPLACE INTO ratings (user_id, movie_id, rating) " 47 | "VALUES (" + std::to_string(userId) + ", " + 48 | std::to_string(movieId) + ", " + 49 | std::to_string(rating) + ");"; 50 | executeQuery(sql); 51 | } 52 | 53 | std::vector Database::getAllRatings() { 54 | std::vector ratings; 55 | const char* sql = "SELECT user_id, movie_id, rating FROM ratings;"; 56 | 57 | sqlite3_stmt* stmt; 58 | int rc = sqlite3_prepare_v2(db_, sql, -1, &stmt, nullptr); 59 | 60 | if (rc != SQLITE_OK) { 61 | throw std::runtime_error("准备SQL语句失败: " + std::string(sqlite3_errmsg(db_))); 62 | } 63 | 64 | while (sqlite3_step(stmt) == SQLITE_ROW) { 65 | int userId = sqlite3_column_int(stmt, 0); 66 | int movieId = sqlite3_column_int(stmt, 1); 67 | double rating = sqlite3_column_double(stmt, 2); 68 | ratings.emplace_back(userId, movieId, rating); 69 | } 70 | 71 | sqlite3_finalize(stmt); 72 | return ratings; 73 | } 74 | 75 | std::vector Database::getUserRatings(int userId) { 76 | std::vector ratings; 77 | std::string sql = "SELECT user_id, movie_id, rating FROM ratings WHERE user_id = " + 78 | std::to_string(userId) + ";"; 79 | 80 | sqlite3_stmt* stmt; 81 | int rc = sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr); 82 | 83 | if (rc != SQLITE_OK) { 84 | throw std::runtime_error("准备SQL语句失败: " + std::string(sqlite3_errmsg(db_))); 85 | } 86 | 87 | while (sqlite3_step(stmt) == SQLITE_ROW) { 88 | int movieId = sqlite3_column_int(stmt, 1); 89 | double rating = sqlite3_column_double(stmt, 2); 90 | ratings.emplace_back(userId, movieId, rating); 91 | } 92 | 93 | sqlite3_finalize(stmt); 94 | return ratings; 95 | } 96 | 97 | std::vector Database::getMovieRatings(int movieId) { 98 | std::vector ratings; 99 | std::string sql = "SELECT user_id, movie_id, rating FROM ratings WHERE movie_id = " + 100 | std::to_string(movieId) + ";"; 101 | 102 | sqlite3_stmt* stmt; 103 | int rc = sqlite3_prepare_v2(db_, sql.c_str(), -1, &stmt, nullptr); 104 | 105 | if (rc != SQLITE_OK) { 106 | throw std::runtime_error("准备SQL语句失败: " + std::string(sqlite3_errmsg(db_))); 107 | } 108 | 109 | while (sqlite3_step(stmt) == SQLITE_ROW) { 110 | int userId = sqlite3_column_int(stmt, 0); 111 | double rating = sqlite3_column_double(stmt, 2); 112 | ratings.emplace_back(userId, movieId, rating); 113 | } 114 | 115 | sqlite3_finalize(stmt); 116 | return ratings; 117 | } -------------------------------------------------------------------------------- /movie_recommender/Database.h: -------------------------------------------------------------------------------- 1 | #ifndef DATABASE_H 2 | #define DATABASE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | struct Rating { 10 | int userId; 11 | int movieId; 12 | double rating; 13 | Rating(int u, int m, double r) : userId(u), movieId(m), rating(r) {} 14 | }; 15 | 16 | class Database { 17 | public: 18 | // 构造函数 19 | explicit Database(const std::string& dbPath); 20 | ~Database(); 21 | 22 | // 初始化数据库 23 | void initialize(); 24 | 25 | // 添加评分 26 | void addRating(int userId, int movieId, double rating); 27 | 28 | // 获取所有评分 29 | std::vector getAllRatings(); 30 | 31 | // 获取用户的所有评分 32 | std::vector getUserRatings(int userId); 33 | 34 | // 获取电影的所有评分 35 | std::vector getMovieRatings(int movieId); 36 | 37 | private: 38 | sqlite3* db_; 39 | std::string dbPath_; 40 | 41 | // 执行SQL语句 42 | void executeQuery(const std::string& sql); 43 | 44 | // 创建表 45 | void createTables(); 46 | }; 47 | 48 | #endif // DATABASE_H -------------------------------------------------------------------------------- /movie_recommender/MovieRecommender.cpp: -------------------------------------------------------------------------------- 1 | #include "MovieRecommender.h" 2 | #include 3 | #include 4 | 5 | MovieRecommender::MovieRecommender(const std::string& dbPath, int numFactors) 6 | : numFactors_(numFactors) { 7 | // 创建数据库连接 8 | db_ = std::make_unique(dbPath); 9 | loadRatings(); 10 | } 11 | 12 | void MovieRecommender::loadRatings() { 13 | // 从数据库加载所有评分 14 | auto ratings = db_->getAllRatings(); 15 | 16 | // 构建评分矩阵 17 | std::set userIds; 18 | std::set movieIds; 19 | 20 | for (const auto& rating : ratings) { 21 | ratingMatrix_[rating.userId][rating.movieId] = rating.rating; 22 | userIds.insert(rating.userId); 23 | movieIds.insert(rating.movieId); 24 | } 25 | 26 | // 创建SVD模型 27 | svd_ = std::make_unique(ratingMatrix_, 28 | numFactors_, 29 | userIds.size(), 30 | movieIds.size()); 31 | } 32 | 33 | void MovieRecommender::addRating(int userId, int movieId, double rating) { 34 | // 添加到数据库 35 | db_->addRating(userId, movieId, rating); 36 | 37 | // 更新评分矩阵 38 | ratingMatrix_[userId][movieId] = rating; 39 | 40 | // 重新加载数据并训练模型 41 | loadRatings(); 42 | } 43 | 44 | void MovieRecommender::trainModel(int numIterations, double learningRate, double regularization) { 45 | if (svd_) { 46 | svd_->train(numIterations, learningRate, regularization); 47 | } 48 | } 49 | 50 | double MovieRecommender::predictRating(int userId, int movieId) { 51 | if (svd_) { 52 | return svd_->predict(userId, movieId); 53 | } 54 | return 0.0; 55 | } 56 | 57 | std::vector> MovieRecommender::getRecommendations(int userId, int topN) { 58 | std::vector> predictions; 59 | 60 | // 获取用户已经评分的电影 61 | std::set ratedMovies; 62 | if (ratingMatrix_.count(userId)) { 63 | for (const auto& rating : ratingMatrix_[userId]) { 64 | ratedMovies.insert(rating.first); 65 | } 66 | } 67 | 68 | // 获取所有可能的电影ID 69 | std::set allMovieIds; 70 | for (const auto& userRatings : ratingMatrix_) { 71 | for (const auto& rating : userRatings.second) { 72 | allMovieIds.insert(rating.first); 73 | } 74 | } 75 | 76 | // 对所有未评分的电影进行预测 77 | for (int movieId : allMovieIds) { 78 | if (ratedMovies.count(movieId) == 0) { 79 | try { 80 | double predictedRating = predictRating(userId, movieId); 81 | predictions.emplace_back(movieId, predictedRating); 82 | } catch (const std::exception& e) { 83 | // 如果预测失败,跳过这个电影 84 | continue; 85 | } 86 | } 87 | } 88 | 89 | // 排序并返回前topN个推荐 90 | std::sort(predictions.begin(), predictions.end(), 91 | [](const auto& a, const auto& b) { 92 | return a.second > b.second; 93 | }); 94 | 95 | if (predictions.size() > topN) { 96 | predictions.resize(topN); 97 | } 98 | 99 | return predictions; 100 | } 101 | 102 | void MovieRecommender::preprocessData() { 103 | // 这里可以添加数据预处理的步骤 104 | // 例如:归一化、处理缺失值等 105 | } -------------------------------------------------------------------------------- /movie_recommender/MovieRecommender.h: -------------------------------------------------------------------------------- 1 | #ifndef MOVIE_RECOMMENDER_H 2 | #define MOVIE_RECOMMENDER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Database.h" 9 | #include "SVD.h" 10 | 11 | class MovieRecommender { 12 | public: 13 | // 构造函数 14 | MovieRecommender(const std::string& dbPath, int numFactors = 100); 15 | 16 | // 添加用户评分 17 | void addRating(int userId, int movieId, double rating); 18 | 19 | // 训练模型 20 | void trainModel(int numIterations = 100, double learningRate = 0.005, double regularization = 0.02); 21 | 22 | // 获取电影推荐 23 | std::vector> getRecommendations(int userId, int topN = 10); 24 | 25 | // 预测用户对电影的评分 26 | double predictRating(int userId, int movieId); 27 | 28 | private: 29 | std::unique_ptr db_; 30 | std::unique_ptr svd_; 31 | int numFactors_; 32 | 33 | // 用户-电影评分矩阵 34 | std::map> ratingMatrix_; 35 | 36 | // 加载评分数据 37 | void loadRatings(); 38 | 39 | // 预处理数据 40 | void preprocessData(); 41 | }; 42 | 43 | #endif // MOVIE_RECOMMENDER_H -------------------------------------------------------------------------------- /movie_recommender/SVD.h: -------------------------------------------------------------------------------- 1 | #ifndef SVD_H 2 | #define SVD_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class SVD { 11 | public: 12 | // 构造函数 13 | SVD(const std::map>& ratingMatrix, 14 | int numFactors, 15 | int numUsers, 16 | int numItems); 17 | 18 | // 训练模型 19 | void train(int numIterations, double learningRate, double regularization); 20 | 21 | // 预测评分 22 | double predict(int userId, int movieId) const; 23 | 24 | // 获取用户特征向量 25 | std::vector getUserFeatures(int userId) const; 26 | 27 | // 获取电影特征向量 28 | std::vector getItemFeatures(int movieId) const; 29 | 30 | private: 31 | int numFactors_; 32 | int numUsers_; 33 | int numItems_; 34 | 35 | // ID映射 36 | std::unordered_map userIdMap_; // 外部ID到内部索引的映射 37 | std::unordered_map movieIdMap_; // 外部ID到内部索引的映射 38 | 39 | // 用户-电影评分矩阵 40 | std::map> ratingMatrix_; 41 | 42 | // 用户特征矩阵 43 | std::vector> userFeatures_; 44 | 45 | // 电影特征矩阵 46 | std::vector> itemFeatures_; 47 | 48 | // 用户偏置 49 | std::vector userBias_; 50 | 51 | // 电影偏置 52 | std::vector itemBias_; 53 | 54 | // 全局平均评分 55 | double globalMean_; 56 | 57 | // 初始化模型参数 58 | void initializeParameters(); 59 | 60 | // 计算全局平均评分 61 | void computeGlobalMean(); 62 | 63 | // 创建ID映射 64 | void createIdMappings(); 65 | 66 | // 获取内部用户索引 67 | int getUserIndex(int userId) const; 68 | 69 | // 获取内部电影索引 70 | int getMovieIndex(int movieId) const; 71 | 72 | // 随机数生成器 73 | std::default_random_engine generator_; 74 | std::normal_distribution distribution_; 75 | }; 76 | 77 | #endif // SVD_H -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/3.31.5/CMakeCCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_C_COMPILER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc") 2 | set(CMAKE_C_COMPILER_ARG1 "") 3 | set(CMAKE_C_COMPILER_ID "AppleClang") 4 | set(CMAKE_C_COMPILER_VERSION "15.0.0.15000309") 5 | set(CMAKE_C_COMPILER_VERSION_INTERNAL "") 6 | set(CMAKE_C_COMPILER_WRAPPER "") 7 | set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "17") 8 | set(CMAKE_C_EXTENSIONS_COMPUTED_DEFAULT "ON") 9 | set(CMAKE_C_STANDARD_LATEST "23") 10 | set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert;c_std_17;c_std_23") 11 | set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") 12 | set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") 13 | set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") 14 | set(CMAKE_C17_COMPILE_FEATURES "c_std_17") 15 | set(CMAKE_C23_COMPILE_FEATURES "c_std_23") 16 | 17 | set(CMAKE_C_PLATFORM_ID "Darwin") 18 | set(CMAKE_C_SIMULATE_ID "") 19 | set(CMAKE_C_COMPILER_FRONTEND_VARIANT "GNU") 20 | set(CMAKE_C_SIMULATE_VERSION "") 21 | 22 | 23 | 24 | 25 | set(CMAKE_AR "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar") 26 | set(CMAKE_C_COMPILER_AR "") 27 | set(CMAKE_RANLIB "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib") 28 | set(CMAKE_C_COMPILER_RANLIB "") 29 | set(CMAKE_LINKER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld") 30 | set(CMAKE_LINKER_LINK "") 31 | set(CMAKE_LINKER_LLD "") 32 | set(CMAKE_C_COMPILER_LINKER "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld") 33 | set(CMAKE_C_COMPILER_LINKER_ID "AppleClang") 34 | set(CMAKE_C_COMPILER_LINKER_VERSION 1053.12) 35 | set(CMAKE_C_COMPILER_LINKER_FRONTEND_VARIANT GNU) 36 | set(CMAKE_MT "") 37 | set(CMAKE_TAPI "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/tapi") 38 | set(CMAKE_COMPILER_IS_GNUCC ) 39 | set(CMAKE_C_COMPILER_LOADED 1) 40 | set(CMAKE_C_COMPILER_WORKS TRUE) 41 | set(CMAKE_C_ABI_COMPILED TRUE) 42 | 43 | set(CMAKE_C_COMPILER_ENV_VAR "CC") 44 | 45 | set(CMAKE_C_COMPILER_ID_RUN 1) 46 | set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) 47 | set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) 48 | set(CMAKE_C_LINKER_PREFERENCE 10) 49 | set(CMAKE_C_LINKER_DEPFILE_SUPPORTED ) 50 | 51 | # Save compiler ABI information. 52 | set(CMAKE_C_SIZEOF_DATA_PTR "8") 53 | set(CMAKE_C_COMPILER_ABI "") 54 | set(CMAKE_C_BYTE_ORDER "LITTLE_ENDIAN") 55 | set(CMAKE_C_LIBRARY_ARCHITECTURE "") 56 | 57 | if(CMAKE_C_SIZEOF_DATA_PTR) 58 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") 59 | endif() 60 | 61 | if(CMAKE_C_COMPILER_ABI) 62 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") 63 | endif() 64 | 65 | if(CMAKE_C_LIBRARY_ARCHITECTURE) 66 | set(CMAKE_LIBRARY_ARCHITECTURE "") 67 | endif() 68 | 69 | set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") 70 | if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) 71 | set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") 72 | endif() 73 | 74 | 75 | 76 | 77 | 78 | set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/15.0.0/include;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/include;/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include") 79 | set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "") 80 | set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/lib;/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/lib/swift") 81 | set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/System/Library/Frameworks") 82 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/3.31.5/CMakeDetermineCompilerABI_C.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/CMakeFiles/3.31.5/CMakeDetermineCompilerABI_C.bin -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/3.31.5/CMakeDetermineCompilerABI_CXX.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/CMakeFiles/3.31.5/CMakeDetermineCompilerABI_CXX.bin -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/3.31.5/CMakeSystem.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_HOST_SYSTEM "Darwin-23.2.0") 2 | set(CMAKE_HOST_SYSTEM_NAME "Darwin") 3 | set(CMAKE_HOST_SYSTEM_VERSION "23.2.0") 4 | set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") 5 | 6 | 7 | 8 | set(CMAKE_SYSTEM "Darwin-23.2.0") 9 | set(CMAKE_SYSTEM_NAME "Darwin") 10 | set(CMAKE_SYSTEM_VERSION "23.2.0") 11 | set(CMAKE_SYSTEM_PROCESSOR "x86_64") 12 | 13 | set(CMAKE_CROSSCOMPILING "FALSE") 14 | 15 | set(CMAKE_SYSTEM_LOADED 1) 16 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/3.31.5/CompilerIdC/CMakeCCompilerId.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/CMakeFiles/3.31.5/CompilerIdC/CMakeCCompilerId.o -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/3.31.5/CompilerIdCXX/CMakeCXXCompilerId.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/CMakeFiles/3.31.5/CompilerIdCXX/CMakeCXXCompilerId.o -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/CMakeDirectoryInformation.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.31 3 | 4 | # Relative path conversion top directories. 5 | set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/Users/zhulei/qt_project/picture_alter/movie_recommender") 6 | set(CMAKE_RELATIVE_PATH_TOP_BINARY "/Users/zhulei/qt_project/picture_alter/movie_recommender/build") 7 | 8 | # Force unix paths in dependencies. 9 | set(CMAKE_FORCE_UNIX_PATHS 1) 10 | 11 | 12 | # The C and CXX include file regular expressions for this directory. 13 | set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") 14 | set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") 15 | set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) 16 | set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) 17 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/Makefile.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.31 3 | 4 | # The generator used is: 5 | set(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") 6 | 7 | # The top level Makefile was generated from the following files: 8 | set(CMAKE_MAKEFILE_DEPENDS 9 | "CMakeCache.txt" 10 | "/Users/zhulei/qt_project/picture_alter/movie_recommender/CMakeLists.txt" 11 | "CMakeFiles/3.31.5/CMakeCCompiler.cmake" 12 | "CMakeFiles/3.31.5/CMakeCXXCompiler.cmake" 13 | "CMakeFiles/3.31.5/CMakeSystem.cmake" 14 | "/usr/local/Homebrew/share/cmake/Modules/CMakeCInformation.cmake" 15 | "/usr/local/Homebrew/share/cmake/Modules/CMakeCXXInformation.cmake" 16 | "/usr/local/Homebrew/share/cmake/Modules/CMakeCommonLanguageInclude.cmake" 17 | "/usr/local/Homebrew/share/cmake/Modules/CMakeGenericSystem.cmake" 18 | "/usr/local/Homebrew/share/cmake/Modules/CMakeInitializeConfigs.cmake" 19 | "/usr/local/Homebrew/share/cmake/Modules/CMakeLanguageInformation.cmake" 20 | "/usr/local/Homebrew/share/cmake/Modules/CMakeSystemSpecificInformation.cmake" 21 | "/usr/local/Homebrew/share/cmake/Modules/CMakeSystemSpecificInitialize.cmake" 22 | "/usr/local/Homebrew/share/cmake/Modules/Compiler/AppleClang-C.cmake" 23 | "/usr/local/Homebrew/share/cmake/Modules/Compiler/AppleClang-CXX.cmake" 24 | "/usr/local/Homebrew/share/cmake/Modules/Compiler/CMakeCommonCompilerMacros.cmake" 25 | "/usr/local/Homebrew/share/cmake/Modules/Compiler/Clang.cmake" 26 | "/usr/local/Homebrew/share/cmake/Modules/Compiler/GNU.cmake" 27 | "/usr/local/Homebrew/share/cmake/Modules/FindPackageHandleStandardArgs.cmake" 28 | "/usr/local/Homebrew/share/cmake/Modules/FindPackageMessage.cmake" 29 | "/usr/local/Homebrew/share/cmake/Modules/FindPkgConfig.cmake" 30 | "/usr/local/Homebrew/share/cmake/Modules/FindSQLite3.cmake" 31 | "/usr/local/Homebrew/share/cmake/Modules/Internal/CMakeCLinkerInformation.cmake" 32 | "/usr/local/Homebrew/share/cmake/Modules/Internal/CMakeCXXLinkerInformation.cmake" 33 | "/usr/local/Homebrew/share/cmake/Modules/Internal/CMakeCommonLinkerInformation.cmake" 34 | "/usr/local/Homebrew/share/cmake/Modules/Linker/AppleClang-C.cmake" 35 | "/usr/local/Homebrew/share/cmake/Modules/Linker/AppleClang-CXX.cmake" 36 | "/usr/local/Homebrew/share/cmake/Modules/Linker/AppleClang.cmake" 37 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Apple-AppleClang-C.cmake" 38 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Apple-AppleClang-CXX.cmake" 39 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Apple-Clang-C.cmake" 40 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Apple-Clang-CXX.cmake" 41 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Apple-Clang.cmake" 42 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Darwin-Initialize.cmake" 43 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Darwin.cmake" 44 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Linker/Apple-AppleClang-C.cmake" 45 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Linker/Apple-AppleClang-CXX.cmake" 46 | "/usr/local/Homebrew/share/cmake/Modules/Platform/Linker/Apple-AppleClang.cmake" 47 | "/usr/local/Homebrew/share/cmake/Modules/Platform/UnixPaths.cmake" 48 | ) 49 | 50 | # The corresponding makefile is: 51 | set(CMAKE_MAKEFILE_OUTPUTS 52 | "Makefile" 53 | "CMakeFiles/cmake.check_cache" 54 | ) 55 | 56 | # Byproducts of CMake generate step: 57 | set(CMAKE_MAKEFILE_PRODUCTS 58 | "CMakeFiles/CMakeDirectoryInformation.cmake" 59 | ) 60 | 61 | # Dependency information for all targets: 62 | set(CMAKE_DEPEND_INFO_FILES 63 | "CMakeFiles/movie_recommender.dir/DependInfo.cmake" 64 | ) 65 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/TargetDirectories.txt: -------------------------------------------------------------------------------- 1 | /Users/zhulei/qt_project/picture_alter/movie_recommender/build/CMakeFiles/movie_recommender.dir 2 | /Users/zhulei/qt_project/picture_alter/movie_recommender/build/CMakeFiles/edit_cache.dir 3 | /Users/zhulei/qt_project/picture_alter/movie_recommender/build/CMakeFiles/rebuild_cache.dir 4 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/cmake.check_cache: -------------------------------------------------------------------------------- 1 | # This file is generated by cmake for dependency checking of the CMakeCache.txt file 2 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/Database.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/CMakeFiles/movie_recommender.dir/Database.cpp.o -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | 2 | # Consider dependencies only in project. 3 | set(CMAKE_DEPENDS_IN_PROJECT_ONLY OFF) 4 | 5 | # The set of languages for which implicit dependencies are needed: 6 | set(CMAKE_DEPENDS_LANGUAGES 7 | ) 8 | 9 | # The set of dependency files which are needed: 10 | set(CMAKE_DEPENDS_DEPENDENCY_FILES 11 | "/Users/zhulei/qt_project/picture_alter/movie_recommender/Database.cpp" "CMakeFiles/movie_recommender.dir/Database.cpp.o" "gcc" "CMakeFiles/movie_recommender.dir/Database.cpp.o.d" 12 | "/Users/zhulei/qt_project/picture_alter/movie_recommender/MovieRecommender.cpp" "CMakeFiles/movie_recommender.dir/MovieRecommender.cpp.o" "gcc" "CMakeFiles/movie_recommender.dir/MovieRecommender.cpp.o.d" 13 | "/Users/zhulei/qt_project/picture_alter/movie_recommender/SVD.cpp" "CMakeFiles/movie_recommender.dir/SVD.cpp.o" "gcc" "CMakeFiles/movie_recommender.dir/SVD.cpp.o.d" 14 | "/Users/zhulei/qt_project/picture_alter/movie_recommender/main.cpp" "CMakeFiles/movie_recommender.dir/main.cpp.o" "gcc" "CMakeFiles/movie_recommender.dir/main.cpp.o.d" 15 | ) 16 | 17 | # Targets to which this target links which contain Fortran sources. 18 | set(CMAKE_Fortran_TARGET_LINKED_INFO_FILES 19 | ) 20 | 21 | # Targets to which this target links which contain Fortran sources. 22 | set(CMAKE_Fortran_TARGET_FORWARD_LINKED_INFO_FILES 23 | ) 24 | 25 | # Fortran module output directory. 26 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 27 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/MovieRecommender.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/CMakeFiles/movie_recommender.dir/MovieRecommender.cpp.o -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/SVD.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/CMakeFiles/movie_recommender.dir/SVD.cpp.o -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/movie_recommender.dir/Database.cpp.o" 3 | "CMakeFiles/movie_recommender.dir/Database.cpp.o.d" 4 | "CMakeFiles/movie_recommender.dir/MovieRecommender.cpp.o" 5 | "CMakeFiles/movie_recommender.dir/MovieRecommender.cpp.o.d" 6 | "CMakeFiles/movie_recommender.dir/SVD.cpp.o" 7 | "CMakeFiles/movie_recommender.dir/SVD.cpp.o.d" 8 | "CMakeFiles/movie_recommender.dir/main.cpp.o" 9 | "CMakeFiles/movie_recommender.dir/main.cpp.o.d" 10 | "movie_recommender" 11 | "movie_recommender.pdb" 12 | ) 13 | 14 | # Per-language clean rules from dependency scanning. 15 | foreach(lang CXX) 16 | include(CMakeFiles/movie_recommender.dir/cmake_clean_${lang}.cmake OPTIONAL) 17 | endforeach() 18 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/compiler_depend.ts: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Timestamp file for compiler generated dependencies management for movie_recommender. 3 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/depend.make: -------------------------------------------------------------------------------- 1 | # Empty dependencies file for movie_recommender. 2 | # This may be replaced when dependencies are built. 3 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.31 3 | 4 | # compile CXX with /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ 5 | CXX_DEFINES = 6 | 7 | CXX_INCLUDES = 8 | 9 | CXX_FLAGS = -std=gnu++17 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 -Wall -Wextra -Wpedantic 10 | 11 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/link.txt: -------------------------------------------------------------------------------- 1 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk -mmacosx-version-min=14.2 -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/movie_recommender.dir/main.cpp.o CMakeFiles/movie_recommender.dir/MovieRecommender.cpp.o CMakeFiles/movie_recommender.dir/Database.cpp.o CMakeFiles/movie_recommender.dir/SVD.cpp.o -o movie_recommender /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.5.sdk/usr/lib/libsqlite3.tbd 2 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/main.cpp.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/CMakeFiles/movie_recommender.dir/main.cpp.o -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/movie_recommender.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 1 2 | CMAKE_PROGRESS_2 = 2 3 | CMAKE_PROGRESS_3 = 3 4 | CMAKE_PROGRESS_4 = 4 5 | CMAKE_PROGRESS_5 = 5 6 | 7 | -------------------------------------------------------------------------------- /movie_recommender/build/CMakeFiles/progress.marks: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /movie_recommender/build/cmake_install.cmake: -------------------------------------------------------------------------------- 1 | # Install script for directory: /Users/zhulei/qt_project/picture_alter/movie_recommender 2 | 3 | # Set the install prefix 4 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 5 | set(CMAKE_INSTALL_PREFIX "/usr/local/Homebrew") 6 | endif() 7 | string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 8 | 9 | # Set the install configuration name. 10 | if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) 11 | if(BUILD_TYPE) 12 | string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" 13 | CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") 14 | else() 15 | set(CMAKE_INSTALL_CONFIG_NAME "") 16 | endif() 17 | message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") 18 | endif() 19 | 20 | # Set the component getting installed. 21 | if(NOT CMAKE_INSTALL_COMPONENT) 22 | if(COMPONENT) 23 | message(STATUS "Install component: \"${COMPONENT}\"") 24 | set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") 25 | else() 26 | set(CMAKE_INSTALL_COMPONENT) 27 | endif() 28 | endif() 29 | 30 | # Is this installation the result of a crosscompile? 31 | if(NOT DEFINED CMAKE_CROSSCOMPILING) 32 | set(CMAKE_CROSSCOMPILING "FALSE") 33 | endif() 34 | 35 | # Set path to fallback-tool for dependency-resolution. 36 | if(NOT DEFINED CMAKE_OBJDUMP) 37 | set(CMAKE_OBJDUMP "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/objdump") 38 | endif() 39 | 40 | string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT 41 | "${CMAKE_INSTALL_MANIFEST_FILES}") 42 | if(CMAKE_INSTALL_LOCAL_ONLY) 43 | file(WRITE "/Users/zhulei/qt_project/picture_alter/movie_recommender/build/install_local_manifest.txt" 44 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 45 | endif() 46 | if(CMAKE_INSTALL_COMPONENT) 47 | if(CMAKE_INSTALL_COMPONENT MATCHES "^[a-zA-Z0-9_.+-]+$") 48 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") 49 | else() 50 | string(MD5 CMAKE_INST_COMP_HASH "${CMAKE_INSTALL_COMPONENT}") 51 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INST_COMP_HASH}.txt") 52 | unset(CMAKE_INST_COMP_HASH) 53 | endif() 54 | else() 55 | set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") 56 | endif() 57 | 58 | if(NOT CMAKE_INSTALL_LOCAL_ONLY) 59 | file(WRITE "/Users/zhulei/qt_project/picture_alter/movie_recommender/build/${CMAKE_INSTALL_MANIFEST}" 60 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 61 | endif() 62 | -------------------------------------------------------------------------------- /movie_recommender/build/movie_recommender: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/movie_recommender -------------------------------------------------------------------------------- /movie_recommender/build/movies.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gitxiaozhu-oss/CPlusPlusKnowledgeVault/19bae240473201b77824ab33782369c1b0210174/movie_recommender/build/movies.db -------------------------------------------------------------------------------- /movie_recommender/main.cpp: -------------------------------------------------------------------------------- 1 | #include "MovieRecommender.h" 2 | #include 3 | #include 4 | 5 | void printRecommendations(const std::vector>& recommendations) { 6 | std::cout << "\n推荐电影列表:" << std::endl; 7 | std::cout << std::setw(10) << "电影ID" << std::setw(15) << "预测评分" << std::endl; 8 | std::cout << std::string(25, '-') << std::endl; 9 | 10 | for (const auto& rec : recommendations) { 11 | std::cout << std::setw(10) << rec.first 12 | << std::setw(15) << std::fixed << std::setprecision(2) << rec.second 13 | << std::endl; 14 | } 15 | } 16 | 17 | int main() { 18 | try { 19 | // 创建推荐系统实例 20 | MovieRecommender recommender("movies.db", 100); 21 | 22 | // 添加一些示例评分数据 23 | std::cout << "添加示例评分数据..." << std::endl; 24 | 25 | // 用户1的评分 26 | recommender.addRating(1, 1, 5.0); // 电影1 27 | recommender.addRating(1, 2, 3.5); // 电影2 28 | recommender.addRating(1, 3, 4.0); // 电影3 29 | 30 | // 用户2的评分 31 | recommender.addRating(2, 1, 3.0); 32 | recommender.addRating(2, 2, 4.0); 33 | recommender.addRating(2, 4, 5.0); 34 | 35 | // 用户3的评分 36 | recommender.addRating(3, 1, 4.0); 37 | recommender.addRating(3, 3, 3.5); 38 | recommender.addRating(3, 4, 4.0); 39 | 40 | // 训练模型 41 | std::cout << "训练推荐模型..." << std::endl; 42 | recommender.trainModel(100, 0.005, 0.02); 43 | 44 | // 为用户1获取推荐 45 | std::cout << "\n为用户1生成推荐..." << std::endl; 46 | auto recommendations = recommender.getRecommendations(1, 5); 47 | printRecommendations(recommendations); 48 | 49 | // 预测特定评分 50 | int userId = 1; 51 | int movieId = 4; 52 | double predictedRating = recommender.predictRating(userId, movieId); 53 | std::cout << "\n预测用户 " << userId << " 对电影 " << movieId 54 | << " 的评分: " << std::fixed << std::setprecision(2) 55 | << predictedRating << std::endl; 56 | 57 | } catch (const std::exception& e) { 58 | std::cerr << "错误: " << e.what() << std::endl; 59 | return 1; 60 | } 61 | 62 | return 0; 63 | } -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/03/03_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | static void die(const char *msg) { 13 | int err = errno; 14 | fprintf(stderr, "[%d] %s\n", err, msg); 15 | abort(); 16 | } 17 | 18 | int main() { 19 | int fd = socket(AF_INET, SOCK_STREAM, 0); 20 | if (fd < 0) { 21 | die("socket()"); 22 | } 23 | 24 | struct sockaddr_in addr = {}; 25 | addr.sin_family = AF_INET; 26 | addr.sin_port = ntohs(1234); 27 | addr.sin_addr.s_addr = ntohl(INADDR_LOOPBACK); // 127.0.0.1 28 | int rv = connect(fd, (const struct sockaddr *)&addr, sizeof(addr)); 29 | if (rv) { 30 | die("connect"); 31 | } 32 | 33 | char msg[] = "hello"; 34 | write(fd, msg, strlen(msg)); 35 | 36 | char rbuf[64] = {}; 37 | ssize_t n = read(fd, rbuf, sizeof(rbuf) - 1); 38 | if (n < 0) { 39 | die("read"); 40 | } 41 | printf("server says: %s\n", rbuf); 42 | close(fd); 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/03/03_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | static void msg(const char *msg) { 13 | fprintf(stderr, "%s\n", msg); 14 | } 15 | 16 | static void die(const char *msg) { 17 | int err = errno; 18 | fprintf(stderr, "[%d] %s\n", err, msg); 19 | abort(); 20 | } 21 | 22 | static void do_something(int connfd) { 23 | char rbuf[64] = {}; 24 | ssize_t n = read(connfd, rbuf, sizeof(rbuf) - 1); 25 | if (n < 0) { 26 | msg("read() error"); 27 | return; 28 | } 29 | fprintf(stderr, "client says: %s\n", rbuf); 30 | 31 | char wbuf[] = "world"; 32 | write(connfd, wbuf, strlen(wbuf)); 33 | } 34 | 35 | int main() { 36 | int fd = socket(AF_INET, SOCK_STREAM, 0); 37 | if (fd < 0) { 38 | die("socket()"); 39 | } 40 | 41 | // this is needed for most server applications 42 | int val = 1; 43 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 44 | 45 | // bind 46 | struct sockaddr_in addr = {}; 47 | addr.sin_family = AF_INET; 48 | addr.sin_port = ntohs(1234); 49 | addr.sin_addr.s_addr = ntohl(0); // wildcard address 0.0.0.0 50 | int rv = bind(fd, (const struct sockaddr *)&addr, sizeof(addr)); 51 | if (rv) { 52 | die("bind()"); 53 | } 54 | 55 | // listen 56 | rv = listen(fd, SOMAXCONN); 57 | if (rv) { 58 | die("listen()"); 59 | } 60 | 61 | while (true) { 62 | // accept 63 | struct sockaddr_in client_addr = {}; 64 | socklen_t addrlen = sizeof(client_addr); 65 | int connfd = accept(fd, (struct sockaddr *)&client_addr, &addrlen); 66 | if (connfd < 0) { 67 | continue; // error 68 | } 69 | 70 | do_something(connfd); 71 | close(connfd); 72 | } 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/04/04_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | static void msg(const char *msg) { 14 | fprintf(stderr, "%s\n", msg); 15 | } 16 | 17 | static void die(const char *msg) { 18 | int err = errno; 19 | fprintf(stderr, "[%d] %s\n", err, msg); 20 | abort(); 21 | } 22 | 23 | static int32_t read_full(int fd, char *buf, size_t n) { 24 | while (n > 0) { 25 | ssize_t rv = read(fd, buf, n); 26 | if (rv <= 0) { 27 | return -1; // error, or unexpected EOF 28 | } 29 | assert((size_t)rv <= n); 30 | n -= (size_t)rv; 31 | buf += rv; 32 | } 33 | return 0; 34 | } 35 | 36 | static int32_t write_all(int fd, const char *buf, size_t n) { 37 | while (n > 0) { 38 | ssize_t rv = write(fd, buf, n); 39 | if (rv <= 0) { 40 | return -1; // error 41 | } 42 | assert((size_t)rv <= n); 43 | n -= (size_t)rv; 44 | buf += rv; 45 | } 46 | return 0; 47 | } 48 | 49 | const size_t k_max_msg = 4096; 50 | 51 | static int32_t query(int fd, const char *text) { 52 | uint32_t len = (uint32_t)strlen(text); 53 | if (len > k_max_msg) { 54 | return -1; 55 | } 56 | 57 | char wbuf[4 + k_max_msg]; 58 | memcpy(wbuf, &len, 4); // assume little endian 59 | memcpy(&wbuf[4], text, len); 60 | if (int32_t err = write_all(fd, wbuf, 4 + len)) { 61 | return err; 62 | } 63 | 64 | // 4 bytes header 65 | char rbuf[4 + k_max_msg + 1]; 66 | errno = 0; 67 | int32_t err = read_full(fd, rbuf, 4); 68 | if (err) { 69 | msg(errno == 0 ? "EOF" : "read() error"); 70 | return err; 71 | } 72 | 73 | memcpy(&len, rbuf, 4); // assume little endian 74 | if (len > k_max_msg) { 75 | msg("too long"); 76 | return -1; 77 | } 78 | 79 | // reply body 80 | err = read_full(fd, &rbuf[4], len); 81 | if (err) { 82 | msg("read() error"); 83 | return err; 84 | } 85 | 86 | // do something 87 | printf("server says: %.*s\n", len, &rbuf[4]); 88 | return 0; 89 | } 90 | 91 | int main() { 92 | int fd = socket(AF_INET, SOCK_STREAM, 0); 93 | if (fd < 0) { 94 | die("socket()"); 95 | } 96 | 97 | struct sockaddr_in addr = {}; 98 | addr.sin_family = AF_INET; 99 | addr.sin_port = ntohs(1234); 100 | addr.sin_addr.s_addr = ntohl(INADDR_LOOPBACK); // 127.0.0.1 101 | int rv = connect(fd, (const struct sockaddr *)&addr, sizeof(addr)); 102 | if (rv) { 103 | die("connect"); 104 | } 105 | 106 | // multiple requests 107 | int32_t err = query(fd, "hello1"); 108 | if (err) { 109 | goto L_DONE; 110 | } 111 | err = query(fd, "hello2"); 112 | if (err) { 113 | goto L_DONE; 114 | } 115 | err = query(fd, "hello3"); 116 | if (err) { 117 | goto L_DONE; 118 | } 119 | 120 | L_DONE: 121 | close(fd); 122 | return 0; 123 | } 124 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/04/04_server.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | static void msg(const char *msg) { 14 | fprintf(stderr, "%s\n", msg); 15 | } 16 | 17 | static void die(const char *msg) { 18 | int err = errno; 19 | fprintf(stderr, "[%d] %s\n", err, msg); 20 | abort(); 21 | } 22 | 23 | const size_t k_max_msg = 4096; 24 | 25 | static int32_t read_full(int fd, char *buf, size_t n) { 26 | while (n > 0) { 27 | ssize_t rv = read(fd, buf, n); 28 | if (rv <= 0) { 29 | return -1; // error, or unexpected EOF 30 | } 31 | assert((size_t)rv <= n); 32 | n -= (size_t)rv; 33 | buf += rv; 34 | } 35 | return 0; 36 | } 37 | 38 | static int32_t write_all(int fd, const char *buf, size_t n) { 39 | while (n > 0) { 40 | ssize_t rv = write(fd, buf, n); 41 | if (rv <= 0) { 42 | return -1; // error 43 | } 44 | assert((size_t)rv <= n); 45 | n -= (size_t)rv; 46 | buf += rv; 47 | } 48 | return 0; 49 | } 50 | 51 | static int32_t one_request(int connfd) { 52 | // 4 bytes header 53 | char rbuf[4 + k_max_msg]; 54 | errno = 0; 55 | int32_t err = read_full(connfd, rbuf, 4); 56 | if (err) { 57 | msg(errno == 0 ? "EOF" : "read() error"); 58 | return err; 59 | } 60 | 61 | uint32_t len = 0; 62 | memcpy(&len, rbuf, 4); // assume little endian 63 | if (len > k_max_msg) { 64 | msg("too long"); 65 | return -1; 66 | } 67 | 68 | // request body 69 | err = read_full(connfd, &rbuf[4], len); 70 | if (err) { 71 | msg("read() error"); 72 | return err; 73 | } 74 | 75 | // do something 76 | fprintf(stderr, "client says: %.*s\n", len, &rbuf[4]); 77 | 78 | // reply using the same protocol 79 | const char reply[] = "world"; 80 | char wbuf[4 + sizeof(reply)]; 81 | len = (uint32_t)strlen(reply); 82 | memcpy(wbuf, &len, 4); 83 | memcpy(&wbuf[4], reply, len); 84 | return write_all(connfd, wbuf, 4 + len); 85 | } 86 | 87 | int main() { 88 | int fd = socket(AF_INET, SOCK_STREAM, 0); 89 | if (fd < 0) { 90 | die("socket()"); 91 | } 92 | 93 | // this is needed for most server applications 94 | int val = 1; 95 | setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); 96 | 97 | // bind 98 | struct sockaddr_in addr = {}; 99 | addr.sin_family = AF_INET; 100 | addr.sin_port = ntohs(1234); 101 | addr.sin_addr.s_addr = ntohl(0); // wildcard address 0.0.0.0 102 | int rv = bind(fd, (const sockaddr *)&addr, sizeof(addr)); 103 | if (rv) { 104 | die("bind()"); 105 | } 106 | 107 | // listen 108 | rv = listen(fd, SOMAXCONN); 109 | if (rv) { 110 | die("listen()"); 111 | } 112 | 113 | while (true) { 114 | // accept 115 | struct sockaddr_in client_addr = {}; 116 | socklen_t addrlen = sizeof(client_addr); 117 | int connfd = accept(fd, (struct sockaddr *)&client_addr, &addrlen); 118 | if (connfd < 0) { 119 | continue; // error 120 | } 121 | 122 | while (true) { 123 | // here the server only serves one client connection at once 124 | int32_t err = one_request(connfd); 125 | if (err) { 126 | break; 127 | } 128 | } 129 | close(connfd); 130 | } 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/06/06_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | static void msg(const char *msg) { 16 | fprintf(stderr, "%s\n", msg); 17 | } 18 | 19 | static void die(const char *msg) { 20 | int err = errno; 21 | fprintf(stderr, "[%d] %s\n", err, msg); 22 | abort(); 23 | } 24 | 25 | static int32_t read_full(int fd, uint8_t *buf, size_t n) { 26 | while (n > 0) { 27 | ssize_t rv = read(fd, buf, n); 28 | if (rv <= 0) { 29 | return -1; // error, or unexpected EOF 30 | } 31 | assert((size_t)rv <= n); 32 | n -= (size_t)rv; 33 | buf += rv; 34 | } 35 | return 0; 36 | } 37 | 38 | static int32_t write_all(int fd, const uint8_t *buf, size_t n) { 39 | while (n > 0) { 40 | ssize_t rv = write(fd, buf, n); 41 | if (rv <= 0) { 42 | return -1; // error 43 | } 44 | assert((size_t)rv <= n); 45 | n -= (size_t)rv; 46 | buf += rv; 47 | } 48 | return 0; 49 | } 50 | 51 | // append to the back 52 | static void 53 | buf_append(std::vector &buf, const uint8_t *data, size_t len) { 54 | buf.insert(buf.end(), data, data + len); 55 | } 56 | 57 | const size_t k_max_msg = 32 << 20; // likely larger than the kernel buffer 58 | 59 | // the `query` function was simply splited into `send_req` and `read_res`. 60 | static int32_t send_req(int fd, const uint8_t *text, size_t len) { 61 | if (len > k_max_msg) { 62 | return -1; 63 | } 64 | 65 | std::vector wbuf; 66 | buf_append(wbuf, (const uint8_t *)&len, 4); 67 | buf_append(wbuf, text, len); 68 | return write_all(fd, wbuf.data(), wbuf.size()); 69 | } 70 | 71 | static int32_t read_res(int fd) { 72 | // 4 bytes header 73 | std::vector rbuf; 74 | rbuf.resize(4); 75 | errno = 0; 76 | int32_t err = read_full(fd, &rbuf[0], 4); 77 | if (err) { 78 | if (errno == 0) { 79 | msg("EOF"); 80 | } else { 81 | msg("read() error"); 82 | } 83 | return err; 84 | } 85 | 86 | uint32_t len = 0; 87 | memcpy(&len, rbuf.data(), 4); // assume little endian 88 | if (len > k_max_msg) { 89 | msg("too long"); 90 | return -1; 91 | } 92 | 93 | // reply body 94 | rbuf.resize(4 + len); 95 | err = read_full(fd, &rbuf[4], len); 96 | if (err) { 97 | msg("read() error"); 98 | return err; 99 | } 100 | 101 | // do something 102 | printf("len:%u data:%.*s\n", len, len < 100 ? len : 100, &rbuf[4]); 103 | return 0; 104 | } 105 | 106 | int main() { 107 | int fd = socket(AF_INET, SOCK_STREAM, 0); 108 | if (fd < 0) { 109 | die("socket()"); 110 | } 111 | 112 | struct sockaddr_in addr = {}; 113 | addr.sin_family = AF_INET; 114 | addr.sin_port = ntohs(1234); 115 | addr.sin_addr.s_addr = ntohl(INADDR_LOOPBACK); // 127.0.0.1 116 | int rv = connect(fd, (const struct sockaddr *)&addr, sizeof(addr)); 117 | if (rv) { 118 | die("connect"); 119 | } 120 | 121 | // multiple pipelined requests 122 | std::vector query_list = { 123 | "hello1", "hello2", "hello3", 124 | // a large message requires multiple event loop iterations 125 | std::string(k_max_msg, 'z'), 126 | "hello5", 127 | }; 128 | for (const std::string &s : query_list) { 129 | int32_t err = send_req(fd, (uint8_t *)s.data(), s.size()); 130 | if (err) { 131 | goto L_DONE; 132 | } 133 | } 134 | for (size_t i = 0; i < query_list.size(); ++i) { 135 | int32_t err = read_res(fd); 136 | if (err) { 137 | goto L_DONE; 138 | } 139 | } 140 | 141 | L_DONE: 142 | close(fd); 143 | return 0; 144 | } 145 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/07/07_client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | 15 | static void msg(const char *msg) { 16 | fprintf(stderr, "%s\n", msg); 17 | } 18 | 19 | static void die(const char *msg) { 20 | int err = errno; 21 | fprintf(stderr, "[%d] %s\n", err, msg); 22 | abort(); 23 | } 24 | 25 | static int32_t read_full(int fd, char *buf, size_t n) { 26 | while (n > 0) { 27 | ssize_t rv = read(fd, buf, n); 28 | if (rv <= 0) { 29 | return -1; // error, or unexpected EOF 30 | } 31 | assert((size_t)rv <= n); 32 | n -= (size_t)rv; 33 | buf += rv; 34 | } 35 | return 0; 36 | } 37 | 38 | static int32_t write_all(int fd, const char *buf, size_t n) { 39 | while (n > 0) { 40 | ssize_t rv = write(fd, buf, n); 41 | if (rv <= 0) { 42 | return -1; // error 43 | } 44 | assert((size_t)rv <= n); 45 | n -= (size_t)rv; 46 | buf += rv; 47 | } 48 | return 0; 49 | } 50 | 51 | const size_t k_max_msg = 4096; 52 | 53 | static int32_t send_req(int fd, const std::vector &cmd) { 54 | uint32_t len = 4; 55 | for (const std::string &s : cmd) { 56 | len += 4 + s.size(); 57 | } 58 | if (len > k_max_msg) { 59 | return -1; 60 | } 61 | 62 | char wbuf[4 + k_max_msg]; 63 | memcpy(&wbuf[0], &len, 4); // assume little endian 64 | uint32_t n = cmd.size(); 65 | memcpy(&wbuf[4], &n, 4); 66 | size_t cur = 8; 67 | for (const std::string &s : cmd) { 68 | uint32_t p = (uint32_t)s.size(); 69 | memcpy(&wbuf[cur], &p, 4); 70 | memcpy(&wbuf[cur + 4], s.data(), s.size()); 71 | cur += 4 + s.size(); 72 | } 73 | return write_all(fd, wbuf, 4 + len); 74 | } 75 | 76 | static int32_t read_res(int fd) { 77 | // 4 bytes header 78 | char rbuf[4 + k_max_msg + 1]; 79 | errno = 0; 80 | int32_t err = read_full(fd, rbuf, 4); 81 | if (err) { 82 | if (errno == 0) { 83 | msg("EOF"); 84 | } else { 85 | msg("read() error"); 86 | } 87 | return err; 88 | } 89 | 90 | uint32_t len = 0; 91 | memcpy(&len, rbuf, 4); // assume little endian 92 | if (len > k_max_msg) { 93 | msg("too long"); 94 | return -1; 95 | } 96 | 97 | // reply body 98 | err = read_full(fd, &rbuf[4], len); 99 | if (err) { 100 | msg("read() error"); 101 | return err; 102 | } 103 | 104 | // print the result 105 | uint32_t rescode = 0; 106 | if (len < 4) { 107 | msg("bad response"); 108 | return -1; 109 | } 110 | memcpy(&rescode, &rbuf[4], 4); 111 | printf("server says: [%u] %.*s\n", rescode, len - 4, &rbuf[8]); 112 | return 0; 113 | } 114 | 115 | int main(int argc, char **argv) { 116 | int fd = socket(AF_INET, SOCK_STREAM, 0); 117 | if (fd < 0) { 118 | die("socket()"); 119 | } 120 | 121 | struct sockaddr_in addr = {}; 122 | addr.sin_family = AF_INET; 123 | addr.sin_port = ntohs(1234); 124 | addr.sin_addr.s_addr = ntohl(INADDR_LOOPBACK); // 127.0.0.1 125 | int rv = connect(fd, (const struct sockaddr *)&addr, sizeof(addr)); 126 | if (rv) { 127 | die("connect"); 128 | } 129 | 130 | std::vector cmd; 131 | for (int i = 1; i < argc; ++i) { 132 | cmd.push_back(argv[i]); 133 | } 134 | int32_t err = send_req(fd, cmd); 135 | if (err) { 136 | goto L_DONE; 137 | } 138 | err = read_res(fd); 139 | if (err) { 140 | goto L_DONE; 141 | } 142 | 143 | L_DONE: 144 | close(fd); 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/08/hashtable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // hashtable node, should be embedded into the payload 8 | struct HNode { 9 | HNode *next = NULL; 10 | uint64_t hcode = 0; 11 | }; 12 | 13 | // a simple fixed-sized hashtable 14 | struct HTab { 15 | HNode **tab = NULL; // array of slots 16 | size_t mask = 0; // power of 2 array size, 2^n - 1 17 | size_t size = 0; // number of keys 18 | }; 19 | 20 | // the real hashtable interface. 21 | // it uses 2 hashtables for progressive rehashing. 22 | struct HMap { 23 | HTab newer; 24 | HTab older; 25 | size_t migrate_pos = 0; 26 | }; 27 | 28 | HNode *hm_lookup(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 29 | void hm_insert(HMap *hmap, HNode *node); 30 | HNode *hm_delete(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 31 | void hm_clear(HMap *hmap); 32 | size_t hm_size(HMap *hmap); 33 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/09/hashtable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // hashtable node, should be embedded into the payload 8 | struct HNode { 9 | HNode *next = NULL; 10 | uint64_t hcode = 0; 11 | }; 12 | 13 | // a simple fixed-sized hashtable 14 | struct HTab { 15 | HNode **tab = NULL; // array of slots 16 | size_t mask = 0; // power of 2 array size, 2^n - 1 17 | size_t size = 0; // number of keys 18 | }; 19 | 20 | // the real hashtable interface. 21 | // it uses 2 hashtables for progressive rehashing. 22 | struct HMap { 23 | HTab newer; 24 | HTab older; 25 | size_t migrate_pos = 0; 26 | }; 27 | 28 | HNode *hm_lookup(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 29 | void hm_insert(HMap *hmap, HNode *node); 30 | HNode *hm_delete(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 31 | void hm_clear(HMap *hmap); 32 | size_t hm_size(HMap *hmap); 33 | // invoke the callback on each node until it returns false 34 | void hm_foreach(HMap *hmap, bool (*f)(HNode *, void *), void *arg); 35 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/10/avl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | struct AVLNode { 8 | AVLNode *parent = NULL; 9 | AVLNode *left = NULL; 10 | AVLNode *right = NULL; 11 | uint32_t height = 0; // subtree height 12 | uint32_t cnt = 0; // subtree size 13 | }; 14 | 15 | inline void avl_init(AVLNode *node) { 16 | node->left = node->right = node->parent = NULL; 17 | node->height = 1; 18 | node->cnt = 1; 19 | } 20 | 21 | // helpers 22 | inline uint32_t avl_height(AVLNode *node) { return node ? node->height : 0; } 23 | inline uint32_t avl_cnt(AVLNode *node) { return node ? node->cnt : 0; } 24 | 25 | // API 26 | AVLNode *avl_fix(AVLNode *node); 27 | AVLNode *avl_del(AVLNode *node); 28 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/11/avl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | struct AVLNode { 8 | AVLNode *parent = NULL; 9 | AVLNode *left = NULL; 10 | AVLNode *right = NULL; 11 | uint32_t height = 0; // subtree height 12 | uint32_t cnt = 0; // subtree size 13 | }; 14 | 15 | inline void avl_init(AVLNode *node) { 16 | node->left = node->right = node->parent = NULL; 17 | node->height = 1; 18 | node->cnt = 1; 19 | } 20 | 21 | // helpers 22 | inline uint32_t avl_height(AVLNode *node) { return node ? node->height : 0; } 23 | inline uint32_t avl_cnt(AVLNode *node) { return node ? node->cnt : 0; } 24 | 25 | // API 26 | AVLNode *avl_fix(AVLNode *node); 27 | AVLNode *avl_del(AVLNode *node); 28 | AVLNode *avl_offset(AVLNode *node, int64_t offset); 29 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/11/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // intrusive data structure 8 | #define container_of(ptr, type, member) ({ \ 9 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 10 | (type *)( (char *)__mptr - offsetof(type, member) );}) 11 | 12 | // FNV hash 13 | inline uint64_t str_hash(const uint8_t *data, size_t len) { 14 | uint32_t h = 0x811C9DC5; 15 | for (size_t i = 0; i < len; i++) { 16 | h = (h + data[i]) * 0x01000193; 17 | } 18 | return h; 19 | } 20 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/11/hashtable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // hashtable node, should be embedded into the payload 8 | struct HNode { 9 | HNode *next = NULL; 10 | uint64_t hcode = 0; 11 | }; 12 | 13 | // a simple fixed-sized hashtable 14 | struct HTab { 15 | HNode **tab = NULL; // array of slots 16 | size_t mask = 0; // power of 2 array size, 2^n - 1 17 | size_t size = 0; // number of keys 18 | }; 19 | 20 | // the real hashtable interface. 21 | // it uses 2 hashtables for progressive rehashing. 22 | struct HMap { 23 | HTab newer; 24 | HTab older; 25 | size_t migrate_pos = 0; 26 | }; 27 | 28 | HNode *hm_lookup(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 29 | void hm_insert(HMap *hmap, HNode *node); 30 | HNode *hm_delete(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 31 | void hm_clear(HMap *hmap); 32 | size_t hm_size(HMap *hmap); 33 | // invoke the callback on each node until it returns false 34 | void hm_foreach(HMap *hmap, bool (*f)(HNode *, void *), void *arg); 35 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/11/test_cmds.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | CASES = r''' 5 | $ ./client zscore asdf n1 6 | (nil) 7 | $ ./client zquery xxx 1 asdf 1 10 8 | (arr) len=0 9 | (arr) end 10 | $ ./client zadd zset 1 n1 11 | (int) 1 12 | $ ./client zadd zset 2 n2 13 | (int) 1 14 | $ ./client zadd zset 1.1 n1 15 | (int) 0 16 | $ ./client zscore zset n1 17 | (dbl) 1.1 18 | $ ./client zquery zset 1 "" 0 10 19 | (arr) len=4 20 | (str) n1 21 | (dbl) 1.1 22 | (str) n2 23 | (dbl) 2 24 | (arr) end 25 | $ ./client zquery zset 1.1 "" 1 10 26 | (arr) len=2 27 | (str) n2 28 | (dbl) 2 29 | (arr) end 30 | $ ./client zquery zset 1.1 "" 2 10 31 | (arr) len=0 32 | (arr) end 33 | $ ./client zrem zset adsf 34 | (int) 0 35 | $ ./client zrem zset n1 36 | (int) 1 37 | $ ./client zquery zset 1 "" 0 10 38 | (arr) len=2 39 | (str) n2 40 | (dbl) 2 41 | (arr) end 42 | ''' 43 | 44 | 45 | import shlex 46 | import subprocess 47 | 48 | cmds = [] 49 | outputs = [] 50 | lines = CASES.splitlines() 51 | for x in lines: 52 | x = x.strip() 53 | if not x: 54 | continue 55 | if x.startswith('$ '): 56 | cmds.append(x[2:]) 57 | outputs.append('') 58 | else: 59 | outputs[-1] = outputs[-1] + x + '\n' 60 | 61 | assert len(cmds) == len(outputs) 62 | for cmd, expect in zip(cmds, outputs): 63 | out = subprocess.check_output(shlex.split(cmd)).decode('utf-8') 64 | assert out == expect, f'cmd:{cmd} out:{out} expect:{expect}' 65 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/11/test_offset.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "avl.h" 3 | 4 | 5 | #define container_of(ptr, type, member) ({ \ 6 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 7 | (type *)( (char *)__mptr - offsetof(type, member) );}) 8 | 9 | 10 | struct Data { 11 | AVLNode node; 12 | uint32_t val = 0; 13 | }; 14 | 15 | struct Container { 16 | AVLNode *root = NULL; 17 | }; 18 | 19 | static void add(Container &c, uint32_t val) { 20 | Data *data = new Data(); 21 | avl_init(&data->node); 22 | data->val = val; 23 | 24 | if (!c.root) { 25 | c.root = &data->node; 26 | return; 27 | } 28 | 29 | AVLNode *cur = c.root; 30 | while (true) { 31 | AVLNode **from = 32 | (val < container_of(cur, Data, node)->val) 33 | ? &cur->left : &cur->right; 34 | if (!*from) { 35 | *from = &data->node; 36 | data->node.parent = cur; 37 | c.root = avl_fix(&data->node); 38 | break; 39 | } 40 | cur = *from; 41 | } 42 | } 43 | 44 | static void dispose(AVLNode *node) { 45 | if (node) { 46 | dispose(node->left); 47 | dispose(node->right); 48 | delete container_of(node, Data, node); 49 | } 50 | } 51 | 52 | static void test_case(uint32_t sz) { 53 | Container c; 54 | for (uint32_t i = 0; i < sz; ++i) { 55 | add(c, i); 56 | } 57 | 58 | AVLNode *min = c.root; 59 | while (min->left) { 60 | min = min->left; 61 | } 62 | for (uint32_t i = 0; i < sz; ++i) { 63 | AVLNode *node = avl_offset(min, (int64_t)i); 64 | assert(container_of(node, Data, node)->val == i); 65 | 66 | for (uint32_t j = 0; j < sz; ++j) { 67 | int64_t offset = (int64_t)j - (int64_t)i; 68 | AVLNode *n2 = avl_offset(node, offset); 69 | assert(container_of(n2, Data, node)->val == j); 70 | } 71 | assert(!avl_offset(node, -(int64_t)i - 1)); 72 | assert(!avl_offset(node, sz - i)); 73 | } 74 | 75 | dispose(c.root); 76 | } 77 | 78 | int main() { 79 | for (uint32_t i = 1; i < 500; ++i) { 80 | test_case(i); 81 | } 82 | return 0; 83 | } 84 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/11/zset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "avl.h" 4 | #include "hashtable.h" 5 | 6 | 7 | struct ZSet { 8 | AVLNode *root = NULL; // index by (score, name) 9 | HMap hmap; // index by name 10 | }; 11 | 12 | struct ZNode { 13 | AVLNode tree; 14 | HNode hmap; 15 | double score = 0; 16 | size_t len = 0; 17 | char name[0]; // flexible array 18 | }; 19 | 20 | bool zset_insert(ZSet *zset, const char *name, size_t len, double score); 21 | ZNode *zset_lookup(ZSet *zset, const char *name, size_t len); 22 | void zset_delete(ZSet *zset, ZNode *node); 23 | ZNode *zset_seekge(ZSet *zset, double score, const char *name, size_t len); 24 | void zset_clear(ZSet *zset); 25 | ZNode *znode_offset(ZNode *node, int64_t offset); 26 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/12/avl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | struct AVLNode { 8 | AVLNode *parent = NULL; 9 | AVLNode *left = NULL; 10 | AVLNode *right = NULL; 11 | uint32_t height = 0; // subtree height 12 | uint32_t cnt = 0; // subtree size 13 | }; 14 | 15 | inline void avl_init(AVLNode *node) { 16 | node->left = node->right = node->parent = NULL; 17 | node->height = 1; 18 | node->cnt = 1; 19 | } 20 | 21 | // helpers 22 | inline uint32_t avl_height(AVLNode *node) { return node ? node->height : 0; } 23 | inline uint32_t avl_cnt(AVLNode *node) { return node ? node->cnt : 0; } 24 | 25 | // API 26 | AVLNode *avl_fix(AVLNode *node); 27 | AVLNode *avl_del(AVLNode *node); 28 | AVLNode *avl_offset(AVLNode *node, int64_t offset); 29 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/12/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // intrusive data structure 8 | #define container_of(ptr, type, member) ({ \ 9 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 10 | (type *)( (char *)__mptr - offsetof(type, member) );}) 11 | 12 | // FNV hash 13 | inline uint64_t str_hash(const uint8_t *data, size_t len) { 14 | uint32_t h = 0x811C9DC5; 15 | for (size_t i = 0; i < len; i++) { 16 | h = (h + data[i]) * 0x01000193; 17 | } 18 | return h; 19 | } 20 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/12/hashtable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // hashtable node, should be embedded into the payload 8 | struct HNode { 9 | HNode *next = NULL; 10 | uint64_t hcode = 0; 11 | }; 12 | 13 | // a simple fixed-sized hashtable 14 | struct HTab { 15 | HNode **tab = NULL; // array of slots 16 | size_t mask = 0; // power of 2 array size, 2^n - 1 17 | size_t size = 0; // number of keys 18 | }; 19 | 20 | // the real hashtable interface. 21 | // it uses 2 hashtables for progressive rehashing. 22 | struct HMap { 23 | HTab newer; 24 | HTab older; 25 | size_t migrate_pos = 0; 26 | }; 27 | 28 | HNode *hm_lookup(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 29 | void hm_insert(HMap *hmap, HNode *node); 30 | HNode *hm_delete(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 31 | void hm_clear(HMap *hmap); 32 | size_t hm_size(HMap *hmap); 33 | // invoke the callback on each node until it returns false 34 | void hm_foreach(HMap *hmap, bool (*f)(HNode *, void *), void *arg); 35 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/12/list.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | struct DList { 7 | DList *prev = NULL; 8 | DList *next = NULL; 9 | }; 10 | 11 | inline void dlist_init(DList *node) { 12 | node->prev = node->next = node; 13 | } 14 | 15 | inline bool dlist_empty(DList *node) { 16 | return node->next == node; 17 | } 18 | 19 | inline void dlist_detach(DList *node) { 20 | DList *prev = node->prev; 21 | DList *next = node->next; 22 | prev->next = next; 23 | next->prev = prev; 24 | } 25 | 26 | inline void dlist_insert_before(DList *target, DList *rookie) { 27 | DList *prev = target->prev; 28 | prev->next = rookie; 29 | rookie->prev = prev; 30 | rookie->next = target; 31 | target->prev = rookie; 32 | } 33 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/12/zset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "avl.h" 4 | #include "hashtable.h" 5 | 6 | 7 | struct ZSet { 8 | AVLNode *root = NULL; // index by (score, name) 9 | HMap hmap; // index by name 10 | }; 11 | 12 | struct ZNode { 13 | AVLNode tree; 14 | HNode hmap; 15 | double score = 0; 16 | size_t len = 0; 17 | char name[0]; // flexible array 18 | }; 19 | 20 | bool zset_insert(ZSet *zset, const char *name, size_t len, double score); 21 | ZNode *zset_lookup(ZSet *zset, const char *name, size_t len); 22 | void zset_delete(ZSet *zset, ZNode *node); 23 | ZNode *zset_seekge(ZSet *zset, double score, const char *name, size_t len); 24 | void zset_clear(ZSet *zset); 25 | ZNode *znode_offset(ZNode *node, int64_t offset); 26 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/13/avl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | struct AVLNode { 8 | AVLNode *parent = NULL; 9 | AVLNode *left = NULL; 10 | AVLNode *right = NULL; 11 | uint32_t height = 0; // subtree height 12 | uint32_t cnt = 0; // subtree size 13 | }; 14 | 15 | inline void avl_init(AVLNode *node) { 16 | node->left = node->right = node->parent = NULL; 17 | node->height = 1; 18 | node->cnt = 1; 19 | } 20 | 21 | // helpers 22 | inline uint32_t avl_height(AVLNode *node) { return node ? node->height : 0; } 23 | inline uint32_t avl_cnt(AVLNode *node) { return node ? node->cnt : 0; } 24 | 25 | // API 26 | AVLNode *avl_fix(AVLNode *node); 27 | AVLNode *avl_del(AVLNode *node); 28 | AVLNode *avl_offset(AVLNode *node, int64_t offset); 29 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/13/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // intrusive data structure 8 | #define container_of(ptr, type, member) ({ \ 9 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 10 | (type *)( (char *)__mptr - offsetof(type, member) );}) 11 | 12 | // FNV hash 13 | inline uint64_t str_hash(const uint8_t *data, size_t len) { 14 | uint32_t h = 0x811C9DC5; 15 | for (size_t i = 0; i < len; i++) { 16 | h = (h + data[i]) * 0x01000193; 17 | } 18 | return h; 19 | } 20 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/13/hashtable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // hashtable node, should be embedded into the payload 8 | struct HNode { 9 | HNode *next = NULL; 10 | uint64_t hcode = 0; 11 | }; 12 | 13 | // a simple fixed-sized hashtable 14 | struct HTab { 15 | HNode **tab = NULL; // array of slots 16 | size_t mask = 0; // power of 2 array size, 2^n - 1 17 | size_t size = 0; // number of keys 18 | }; 19 | 20 | // the real hashtable interface. 21 | // it uses 2 hashtables for progressive rehashing. 22 | struct HMap { 23 | HTab newer; 24 | HTab older; 25 | size_t migrate_pos = 0; 26 | }; 27 | 28 | HNode *hm_lookup(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 29 | void hm_insert(HMap *hmap, HNode *node); 30 | HNode *hm_delete(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 31 | void hm_clear(HMap *hmap); 32 | size_t hm_size(HMap *hmap); 33 | // invoke the callback on each node until it returns false 34 | void hm_foreach(HMap *hmap, bool (*f)(HNode *, void *), void *arg); 35 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/13/heap.cpp: -------------------------------------------------------------------------------- 1 | #include "heap.h" 2 | 3 | 4 | static size_t heap_parent(size_t i) { 5 | return (i + 1) / 2 - 1; 6 | } 7 | 8 | static size_t heap_left(size_t i) { 9 | return i * 2 + 1; 10 | } 11 | 12 | static size_t heap_right(size_t i) { 13 | return i * 2 + 2; 14 | } 15 | 16 | static void heap_up(HeapItem *a, size_t pos) { 17 | HeapItem t = a[pos]; 18 | while (pos > 0 && a[heap_parent(pos)].val > t.val) { 19 | // swap with the parent 20 | a[pos] = a[heap_parent(pos)]; 21 | *a[pos].ref = pos; 22 | pos = heap_parent(pos); 23 | } 24 | a[pos] = t; 25 | *a[pos].ref = pos; 26 | } 27 | 28 | static void heap_down(HeapItem *a, size_t pos, size_t len) { 29 | HeapItem t = a[pos]; 30 | while (true) { 31 | // find the smallest one among the parent and their kids 32 | size_t l = heap_left(pos); 33 | size_t r = heap_right(pos); 34 | size_t min_pos = pos; 35 | uint64_t min_val = t.val; 36 | if (l < len && a[l].val < min_val) { 37 | min_pos = l; 38 | min_val = a[l].val; 39 | } 40 | if (r < len && a[r].val < min_val) { 41 | min_pos = r; 42 | } 43 | if (min_pos == pos) { 44 | break; 45 | } 46 | // swap with the kid 47 | a[pos] = a[min_pos]; 48 | *a[pos].ref = pos; 49 | pos = min_pos; 50 | } 51 | a[pos] = t; 52 | *a[pos].ref = pos; 53 | } 54 | 55 | void heap_update(HeapItem *a, size_t pos, size_t len) { 56 | if (pos > 0 && a[heap_parent(pos)].val > a[pos].val) { 57 | heap_up(a, pos); 58 | } else { 59 | heap_down(a, pos, len); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/13/heap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | struct HeapItem { 8 | uint64_t val = 0; 9 | size_t *ref = NULL; 10 | }; 11 | 12 | void heap_update(HeapItem *a, size_t pos, size_t len); 13 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/13/list.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | struct DList { 7 | DList *prev = NULL; 8 | DList *next = NULL; 9 | }; 10 | 11 | inline void dlist_init(DList *node) { 12 | node->prev = node->next = node; 13 | } 14 | 15 | inline bool dlist_empty(DList *node) { 16 | return node->next == node; 17 | } 18 | 19 | inline void dlist_detach(DList *node) { 20 | DList *prev = node->prev; 21 | DList *next = node->next; 22 | prev->next = next; 23 | next->prev = prev; 24 | } 25 | 26 | inline void dlist_insert_before(DList *target, DList *rookie) { 27 | DList *prev = target->prev; 28 | prev->next = rookie; 29 | rookie->prev = prev; 30 | rookie->next = target; 31 | target->prev = rookie; 32 | } 33 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/13/test_heap.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "heap.cpp" 5 | 6 | 7 | struct Data { 8 | size_t heap_idx = -1; 9 | }; 10 | 11 | struct Container { 12 | std::vector heap; 13 | std::multimap map; 14 | }; 15 | 16 | static void dispose(Container &c) { 17 | for (auto p : c.map) { 18 | delete p.second; 19 | } 20 | } 21 | 22 | static void add(Container &c, uint64_t val) { 23 | Data *d = new Data(); 24 | c.map.insert(std::make_pair(val, d)); 25 | HeapItem item; 26 | item.ref = &d->heap_idx; 27 | item.val = val; 28 | c.heap.push_back(item); 29 | heap_update(c.heap.data(), c.heap.size() - 1, c.heap.size()); 30 | } 31 | 32 | static void del(Container &c, uint64_t val) { 33 | auto it = c.map.find(val); 34 | assert(it != c.map.end()); 35 | Data *d = it->second; 36 | assert(c.heap.at(d->heap_idx).val == val); 37 | assert(c.heap.at(d->heap_idx).ref == &d->heap_idx); 38 | c.heap[d->heap_idx] = c.heap.back(); 39 | c.heap.pop_back(); 40 | if (d->heap_idx < c.heap.size()) { 41 | heap_update(c.heap.data(), d->heap_idx, c.heap.size()); 42 | } 43 | delete d; 44 | c.map.erase(it); 45 | } 46 | 47 | static void verify(Container &c) { 48 | assert(c.heap.size() == c.map.size()); 49 | for (size_t i = 0; i < c.heap.size(); ++i) { 50 | size_t l = heap_left(i); 51 | size_t r = heap_right(i); 52 | assert(l >= c.heap.size() || c.heap[l].val >= c.heap[i].val); 53 | assert(r >= c.heap.size() || c.heap[r].val >= c.heap[i].val); 54 | assert(*c.heap[i].ref == i); 55 | } 56 | } 57 | 58 | static void test_case(size_t sz) { 59 | for (uint32_t j = 0; j < 2 + sz * 2; ++j) { 60 | Container c; 61 | for (uint32_t i = 0; i < sz; ++i) { 62 | add(c, 1 + i * 2); 63 | } 64 | verify(c); 65 | 66 | add(c, j); 67 | verify(c); 68 | 69 | dispose(c); 70 | } 71 | 72 | for (uint32_t j = 0; j < sz; ++j) { 73 | Container c; 74 | for (uint32_t i = 0; i < sz; ++i) { 75 | add(c, i); 76 | } 77 | verify(c); 78 | 79 | del(c, j); 80 | verify(c); 81 | 82 | dispose(c); 83 | } 84 | } 85 | 86 | int main() { 87 | for (uint32_t i = 0; i < 200; ++i) { 88 | test_case(i); 89 | } 90 | return 0; 91 | } 92 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/13/zset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "avl.h" 4 | #include "hashtable.h" 5 | 6 | 7 | struct ZSet { 8 | AVLNode *root = NULL; // index by (score, name) 9 | HMap hmap; // index by name 10 | }; 11 | 12 | struct ZNode { 13 | AVLNode tree; 14 | HNode hmap; 15 | double score = 0; 16 | size_t len = 0; 17 | char name[0]; // flexible array 18 | }; 19 | 20 | bool zset_insert(ZSet *zset, const char *name, size_t len, double score); 21 | ZNode *zset_lookup(ZSet *zset, const char *name, size_t len); 22 | void zset_delete(ZSet *zset, ZNode *node); 23 | ZNode *zset_seekge(ZSet *zset, double score, const char *name, size_t len); 24 | void zset_clear(ZSet *zset); 25 | ZNode *znode_offset(ZNode *node, int64_t offset); 26 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/14/avl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | struct AVLNode { 8 | AVLNode *parent = NULL; 9 | AVLNode *left = NULL; 10 | AVLNode *right = NULL; 11 | uint32_t height = 0; // subtree height 12 | uint32_t cnt = 0; // subtree size 13 | }; 14 | 15 | inline void avl_init(AVLNode *node) { 16 | node->left = node->right = node->parent = NULL; 17 | node->height = 1; 18 | node->cnt = 1; 19 | } 20 | 21 | // helpers 22 | inline uint32_t avl_height(AVLNode *node) { return node ? node->height : 0; } 23 | inline uint32_t avl_cnt(AVLNode *node) { return node ? node->cnt : 0; } 24 | 25 | // API 26 | AVLNode *avl_fix(AVLNode *node); 27 | AVLNode *avl_del(AVLNode *node); 28 | AVLNode *avl_offset(AVLNode *node, int64_t offset); 29 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/14/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // intrusive data structure 8 | #define container_of(ptr, type, member) ({ \ 9 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 10 | (type *)( (char *)__mptr - offsetof(type, member) );}) 11 | 12 | // FNV hash 13 | inline uint64_t str_hash(const uint8_t *data, size_t len) { 14 | uint32_t h = 0x811C9DC5; 15 | for (size_t i = 0; i < len; i++) { 16 | h = (h + data[i]) * 0x01000193; 17 | } 18 | return h; 19 | } 20 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/14/hashtable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | // hashtable node, should be embedded into the payload 8 | struct HNode { 9 | HNode *next = NULL; 10 | uint64_t hcode = 0; 11 | }; 12 | 13 | // a simple fixed-sized hashtable 14 | struct HTab { 15 | HNode **tab = NULL; // array of slots 16 | size_t mask = 0; // power of 2 array size, 2^n - 1 17 | size_t size = 0; // number of keys 18 | }; 19 | 20 | // the real hashtable interface. 21 | // it uses 2 hashtables for progressive rehashing. 22 | struct HMap { 23 | HTab newer; 24 | HTab older; 25 | size_t migrate_pos = 0; 26 | }; 27 | 28 | HNode *hm_lookup(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 29 | void hm_insert(HMap *hmap, HNode *node); 30 | HNode *hm_delete(HMap *hmap, HNode *key, bool (*eq)(HNode *, HNode *)); 31 | void hm_clear(HMap *hmap); 32 | size_t hm_size(HMap *hmap); 33 | // invoke the callback on each node until it returns false 34 | void hm_foreach(HMap *hmap, bool (*f)(HNode *, void *), void *arg); 35 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/14/heap.cpp: -------------------------------------------------------------------------------- 1 | #include "heap.h" 2 | 3 | 4 | static size_t heap_parent(size_t i) { 5 | return (i + 1) / 2 - 1; 6 | } 7 | 8 | static size_t heap_left(size_t i) { 9 | return i * 2 + 1; 10 | } 11 | 12 | static size_t heap_right(size_t i) { 13 | return i * 2 + 2; 14 | } 15 | 16 | static void heap_up(HeapItem *a, size_t pos) { 17 | HeapItem t = a[pos]; 18 | while (pos > 0 && a[heap_parent(pos)].val > t.val) { 19 | // swap with the parent 20 | a[pos] = a[heap_parent(pos)]; 21 | *a[pos].ref = pos; 22 | pos = heap_parent(pos); 23 | } 24 | a[pos] = t; 25 | *a[pos].ref = pos; 26 | } 27 | 28 | static void heap_down(HeapItem *a, size_t pos, size_t len) { 29 | HeapItem t = a[pos]; 30 | while (true) { 31 | // find the smallest one among the parent and their kids 32 | size_t l = heap_left(pos); 33 | size_t r = heap_right(pos); 34 | size_t min_pos = pos; 35 | uint64_t min_val = t.val; 36 | if (l < len && a[l].val < min_val) { 37 | min_pos = l; 38 | min_val = a[l].val; 39 | } 40 | if (r < len && a[r].val < min_val) { 41 | min_pos = r; 42 | } 43 | if (min_pos == pos) { 44 | break; 45 | } 46 | // swap with the kid 47 | a[pos] = a[min_pos]; 48 | *a[pos].ref = pos; 49 | pos = min_pos; 50 | } 51 | a[pos] = t; 52 | *a[pos].ref = pos; 53 | } 54 | 55 | void heap_update(HeapItem *a, size_t pos, size_t len) { 56 | if (pos > 0 && a[heap_parent(pos)].val > a[pos].val) { 57 | heap_up(a, pos); 58 | } else { 59 | heap_down(a, pos, len); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/14/heap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | 7 | struct HeapItem { 8 | uint64_t val = 0; 9 | size_t *ref = NULL; 10 | }; 11 | 12 | void heap_update(HeapItem *a, size_t pos, size_t len); 13 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/14/list.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | 6 | struct DList { 7 | DList *prev = NULL; 8 | DList *next = NULL; 9 | }; 10 | 11 | inline void dlist_init(DList *node) { 12 | node->prev = node->next = node; 13 | } 14 | 15 | inline bool dlist_empty(DList *node) { 16 | return node->next == node; 17 | } 18 | 19 | inline void dlist_detach(DList *node) { 20 | DList *prev = node->prev; 21 | DList *next = node->next; 22 | prev->next = next; 23 | next->prev = prev; 24 | } 25 | 26 | inline void dlist_insert_before(DList *target, DList *rookie) { 27 | DList *prev = target->prev; 28 | prev->next = rookie; 29 | rookie->prev = prev; 30 | rookie->next = target; 31 | target->prev = rookie; 32 | } 33 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/14/thread_pool.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "thread_pool.h" 3 | 4 | 5 | static void *worker(void *arg) { 6 | TheadPool *tp = (TheadPool *)arg; 7 | while (true) { 8 | pthread_mutex_lock(&tp->mu); 9 | // wait for the condition: a non-empty queue 10 | while (tp->queue.empty()) { 11 | pthread_cond_wait(&tp->not_empty, &tp->mu); 12 | } 13 | 14 | // got the job 15 | Work w = tp->queue.front(); 16 | tp->queue.pop_front(); 17 | pthread_mutex_unlock(&tp->mu); 18 | 19 | // do the work 20 | w.f(w.arg); 21 | } 22 | return NULL; 23 | } 24 | 25 | void thread_pool_init(TheadPool *tp, size_t num_threads) { 26 | assert(num_threads > 0); 27 | 28 | int rv = pthread_mutex_init(&tp->mu, NULL); 29 | assert(rv == 0); 30 | rv = pthread_cond_init(&tp->not_empty, NULL); 31 | assert(rv == 0); 32 | 33 | tp->threads.resize(num_threads); 34 | for (size_t i = 0; i < num_threads; ++i) { 35 | int rv = pthread_create(&tp->threads[i], NULL, &worker, tp); 36 | assert(rv == 0); 37 | } 38 | } 39 | 40 | void thread_pool_queue(TheadPool *tp, void (*f)(void *), void *arg) { 41 | pthread_mutex_lock(&tp->mu); 42 | tp->queue.push_back(Work {f, arg}); 43 | pthread_cond_signal(&tp->not_empty); 44 | pthread_mutex_unlock(&tp->mu); 45 | } 46 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/14/thread_pool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | struct Work { 10 | void (*f)(void *) = NULL; 11 | void *arg = NULL; 12 | }; 13 | 14 | struct TheadPool { 15 | std::vector threads; 16 | std::deque queue; 17 | pthread_mutex_t mu; 18 | pthread_cond_t not_empty; 19 | }; 20 | 21 | void thread_pool_init(TheadPool *tp, size_t num_threads); 22 | void thread_pool_queue(TheadPool *tp, void (*f)(void *), void *arg); 23 | -------------------------------------------------------------------------------- /使用C:C++构建自己的redis/14/zset.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "avl.h" 4 | #include "hashtable.h" 5 | 6 | 7 | struct ZSet { 8 | AVLNode *root = NULL; // index by (score, name) 9 | HMap hmap; // index by name 10 | }; 11 | 12 | struct ZNode { 13 | AVLNode tree; 14 | HNode hmap; 15 | double score = 0; 16 | size_t len = 0; 17 | char name[0]; // flexible array 18 | }; 19 | 20 | bool zset_insert(ZSet *zset, const char *name, size_t len, double score); 21 | ZNode *zset_lookup(ZSet *zset, const char *name, size_t len); 22 | void zset_delete(ZSet *zset, ZNode *node); 23 | ZNode *zset_seekge(ZSet *zset, double score, const char *name, size_t len); 24 | void zset_clear(ZSet *zset); 25 | ZNode *znode_offset(ZNode *node, int64_t offset); 26 | -------------------------------------------------------------------------------- /超高并发场景优化的定制化C++ STL 库/HighConcurrencySTL/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | project(HighConcurrencySTL VERSION 0.1.0 LANGUAGES CXX) 3 | 4 | # 设置 C++20 标准 5 | set(CMAKE_CXX_STANDARD 20) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | set(CMAKE_CXX_EXTENSIONS OFF) 8 | 9 | # 设置编译选项 10 | if(MSVC) 11 | add_compile_options(/W4 /WX) 12 | else() 13 | add_compile_options(-Wall -Wextra -Wpedantic -Werror) 14 | endif() 15 | 16 | # 添加第三方依赖 17 | include(FetchContent) 18 | 19 | # 添加 Google Test 20 | FetchContent_Declare( 21 | googletest 22 | GIT_REPOSITORY https://github.com/google/googletest.git 23 | GIT_TAG release-1.12.1 24 | ) 25 | FetchContent_MakeAvailable(googletest) 26 | 27 | # 添加 Google Benchmark 28 | FetchContent_Declare( 29 | benchmark 30 | GIT_REPOSITORY https://github.com/google/benchmark.git 31 | GIT_TAG v1.8.3 32 | ) 33 | set(BENCHMARK_ENABLE_TESTING OFF) 34 | FetchContent_MakeAvailable(benchmark) 35 | 36 | # 添加 TBB 37 | find_package(TBB REQUIRED) 38 | 39 | # 添加头文件目录 40 | include_directories(${PROJECT_SOURCE_DIR}/include) 41 | 42 | # 添加库目标 43 | add_library(hcstl INTERFACE) 44 | target_include_directories(hcstl INTERFACE 45 | $ 46 | $ 47 | ) 48 | 49 | # 添加子目录 50 | add_subdirectory(tests) 51 | add_subdirectory(benchmarks) 52 | add_subdirectory(examples) 53 | 54 | # 安装配置 55 | install(TARGETS hcstl 56 | EXPORT hcstl-targets 57 | LIBRARY DESTINATION lib 58 | ARCHIVE DESTINATION lib 59 | RUNTIME DESTINATION bin 60 | INCLUDES DESTINATION include 61 | ) 62 | 63 | install(DIRECTORY include/hcstl 64 | DESTINATION include 65 | FILES_MATCHING PATTERN "*.hpp" 66 | ) 67 | 68 | # 导出配置 69 | install(EXPORT hcstl-targets 70 | FILE hcstl-targets.cmake 71 | NAMESPACE hcstl:: 72 | DESTINATION lib/cmake/hcstl 73 | ) 74 | 75 | # 生成并安装版本文件 76 | include(CMakePackageConfigHelpers) 77 | write_basic_package_version_file( 78 | "${CMAKE_CURRENT_BINARY_DIR}/hcstl-config-version.cmake" 79 | VERSION ${PROJECT_VERSION} 80 | COMPATIBILITY SameMajorVersion 81 | ) 82 | 83 | # 配置并安装包配置文件 84 | configure_package_config_file( 85 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake/hcstl-config.cmake.in" 86 | "${CMAKE_CURRENT_BINARY_DIR}/hcstl-config.cmake" 87 | INSTALL_DESTINATION lib/cmake/hcstl 88 | ) 89 | 90 | install(FILES 91 | "${CMAKE_CURRENT_BINARY_DIR}/hcstl-config.cmake" 92 | "${CMAKE_CURRENT_BINARY_DIR}/hcstl-config-version.cmake" 93 | DESTINATION lib/cmake/hcstl 94 | ) -------------------------------------------------------------------------------- /超高并发场景优化的定制化C++ STL 库/HighConcurrencySTL/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 HighConcurrencySTL 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /超高并发场景优化的定制化C++ STL 库/HighConcurrencySTL/benchmarks/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(container_benchmarks 2 | container_benchmarks.cpp 3 | ) 4 | 5 | target_link_libraries(container_benchmarks 6 | PRIVATE 7 | hcstl 8 | benchmark::benchmark 9 | benchmark::benchmark_main 10 | ) -------------------------------------------------------------------------------- /超高并发场景优化的定制化C++ STL 库/HighConcurrencySTL/cmake/hcstl-config.cmake.in: -------------------------------------------------------------------------------- 1 | @PACKAGE_INIT@ 2 | 3 | include(CMakeFindDependencyMacro) 4 | find_dependency(TBB) 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/hcstl-targets.cmake") 7 | 8 | check_required_components(hcstl) -------------------------------------------------------------------------------- /超高并发场景优化的定制化C++ STL 库/HighConcurrencySTL/examples/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(container_example 2 | container_example.cpp 3 | ) 4 | 5 | target_link_libraries(container_example 6 | PRIVATE 7 | hcstl 8 | ) -------------------------------------------------------------------------------- /超高并发场景优化的定制化C++ STL 库/HighConcurrencySTL/include/hcstl/concurrent_vector.hpp: -------------------------------------------------------------------------------- 1 | #ifndef HCSTL_CONCURRENT_VECTOR_HPP 2 | #define HCSTL_CONCURRENT_VECTOR_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | namespace hcstl { 11 | 12 | /** 13 | * @brief 高性能并发向量容器 14 | * 15 | * @tparam T 元素类型 16 | * @tparam Allocator 分配器类型 17 | */ 18 | template> 19 | class concurrent_vector 20 | { 21 | public: 22 | using value_type = T; 23 | using allocator_type = Allocator; 24 | using size_type = std::size_t; 25 | using reference = value_type&; 26 | using const_reference = const value_type&; 27 | using pointer = typename std::allocator_traits::pointer; 28 | using const_pointer = typename std::allocator_traits::const_pointer; 29 | 30 | static constexpr size_type SEGMENT_SIZE = 1024; 31 | 32 | private: 33 | struct Segment 34 | { 35 | std::array data; 36 | std::atomic size{0}; 37 | }; 38 | 39 | std::vector> segments_; 40 | std::atomic size_{0}; 41 | mutable std::shared_mutex mutex_; 42 | Allocator allocator_; 43 | 44 | public: 45 | /** 46 | * @brief 构造函数 47 | */ 48 | concurrent_vector() = default; 49 | 50 | /** 51 | * @brief 析构函数 52 | */ 53 | ~concurrent_vector() = default; 54 | 55 | /** 56 | * @brief 向向量尾部添加元素 57 | * 58 | * @param value 要添加的元素值 59 | */ 60 | void push_back(const T& value) 61 | { 62 | size_type current_size = size_.load(std::memory_order_relaxed); 63 | size_type segment_index = current_size / SEGMENT_SIZE; 64 | size_type offset = current_size % SEGMENT_SIZE; 65 | 66 | // 确保有足够的段 67 | ensure_segment(segment_index); 68 | 69 | // 添加元素 70 | segments_[segment_index]->data[offset] = value; 71 | segments_[segment_index]->size.fetch_add(1, std::memory_order_release); 72 | size_.fetch_add(1, std::memory_order_release); 73 | } 74 | 75 | /** 76 | * @brief 访问指定位置的元素 77 | * 78 | * @param index 要访问的元素索引 79 | * @return const_reference 元素的常量引用 80 | * @throw std::out_of_range 如果索引超出范围 81 | */ 82 | const_reference at(size_type index) const 83 | { 84 | if (index >= size()) 85 | { 86 | throw std::out_of_range("Index out of range"); 87 | } 88 | 89 | size_type segment_index = index / SEGMENT_SIZE; 90 | size_type offset = index % SEGMENT_SIZE; 91 | 92 | std::shared_lock lock(mutex_); 93 | return segments_[segment_index]->data[offset]; 94 | } 95 | 96 | /** 97 | * @brief 获取向量的当前大小 98 | * 99 | * @return size_type 向量中的元素数量 100 | */ 101 | size_type size() const noexcept 102 | { 103 | return size_.load(std::memory_order_acquire); 104 | } 105 | 106 | /** 107 | * @brief 检查向量是否为空 108 | * 109 | * @return bool 如果向量为空返回true,否则返回false 110 | */ 111 | bool empty() const noexcept 112 | { 113 | return size() == 0; 114 | } 115 | 116 | private: 117 | /** 118 | * @brief 确保指定索引的段存在 119 | * 120 | * @param segment_index 段索引 121 | */ 122 | void ensure_segment(size_type segment_index) 123 | { 124 | std::unique_lock lock(mutex_); 125 | if (segment_index >= segments_.size()) 126 | { 127 | segments_.resize(segment_index + 1); 128 | } 129 | if (!segments_[segment_index]) 130 | { 131 | segments_[segment_index] = std::make_unique(); 132 | } 133 | } 134 | }; 135 | 136 | } // namespace hcstl 137 | 138 | #endif // HCSTL_CONCURRENT_VECTOR_HPP -------------------------------------------------------------------------------- /超高并发场景优化的定制化C++ STL 库/HighConcurrencySTL/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_testing() 2 | 3 | add_executable(container_tests 4 | container_tests.cpp 5 | ) 6 | 7 | target_link_libraries(container_tests 8 | PRIVATE 9 | hcstl 10 | GTest::gtest_main 11 | GTest::gmock 12 | ) 13 | 14 | include(GoogleTest) 15 | gtest_discover_tests(container_tests) --------------------------------------------------------------------------------