C++运行时构建多组向量/映射插入BST及气象数据处理问询
针对你这个在现有气象数据处理程序基础上添加BST构建功能的需求,我整理了一套可落地的技术方案,咱们一步步来看怎么实现:
核心思路与整体架构
首先明确核心目标:基于原有单文件气象数据(5万行10分钟均值),先按四种需求完成数据分组/统计,再将不同维度的向量/映射数据插入二叉搜索树(BST),同时保留原有气象属性计算功能。整体流程是:数据解析 → 按需求构建统计数据集 → 插入BST → 基于BST实现查询/导出。
1. 定义核心数据结构
先把气象数据和BST节点的基础结构定义清楚,确保后续逻辑有统一的操作对象:
气象数据结构体
对应每行10分钟的原始数据,包含时间维度和气象属性:
struct WeatherData { int year; int month; int day; int period; // 一天内的10分钟时段(共144个:24*6) double temperature; double humidity; double windSpeed; // 可扩展其他气象属性,如气压、降水量等 };
通用模板BST节点与类
为了适配不同维度的键(年月、年份)和值(均值、月份统计映射),用模板实现BST,保证通用性:
template <typename Key, typename Value> struct BSTNode { Key key; Value value; BSTNode* left; BSTNode* right; BSTNode(const Key& k, const Value& v) : key(k), value(v), left(nullptr), right(nullptr) {} }; template <typename Key, typename Value> class BST { private: BSTNode<Key, Value>* root; // 递归插入辅助函数 BSTNode<Key, Value>* insertHelper(BSTNode<Key, Value>* node, const Key& key, const Value& value) { if (node == nullptr) return new BSTNode<Key, Value>(key, value); if (key < node->key) node->left = insertHelper(node->left, key, value); else if (key > node->key) node->right = insertHelper(node->right, key, value); // 键重复时可选择更新值或忽略,这里默认保留原有值 return node; } // 递归查找辅助函数 BSTNode<Key, Value>* searchHelper(BSTNode<Key, Value>* node, const Key& key) { if (node == nullptr || node->key == key) return node; return key < node->key ? searchHelper(node->left, key) : searchHelper(node->right, key); } // 中序遍历辅助函数(有序输出数据) void inorderHelper(BSTNode<Key, Value>* node, std::function<void(const Key&, const Value&)> visitor) { if (node == nullptr) return; inorderHelper(node->left, visitor); visitor(node->key, node->value); inorderHelper(node->right, visitor); } // 销毁节点避免内存泄漏 void destroyNode(BSTNode<Key, Value>* node) { if (node == nullptr) return; destroyNode(node->left); destroyNode(node->right); delete node; } public: BST() : root(nullptr) {} ~BST() { destroyNode(root); } void insert(const Key& key, const Value& value) { root = insertHelper(root, key, value); } BSTNode<Key, Value>* search(const Key& key) { return searchHelper(root, key); } void inorderTraversal(std::function<void(const Key&, const Value&)> visitor) { inorderHelper(root, visitor); } };
2. 数据预处理与BST构建
针对四种需求,分别构建对应的数据集并插入BST:
需求a:指定年月的气象属性平均值
构建以(年,月)为键、属性均值为值的BST:
// 解析原始文件为WeatherData向量 std::vector<WeatherData> parseWeatherFile(const std::string& filename) { std::vector<WeatherData> data; std::ifstream file(filename); std::string line; while (std::getline(file, line)) { std::istringstream iss(line); WeatherData wd; // 假设每行格式:年 月 日 时段 温度 湿度 风速 iss >> wd.year >> wd.month >> wd.day >> wd.period >> wd.temperature >> wd.humidity >> wd.windSpeed; data.push_back(wd); } return data; } // 构建年月均值BST(以温度为例,其他属性可复用逻辑) BST<std::pair<int, int>, double> buildMonthlyMeanBST(const std::vector<WeatherData>& data) { BST<std::pair<int, int>, double> bst; std::map<std::pair<int, int>, std::vector<double>> monthlyTempMap; // 按年月分组原始数据 for (const auto& wd : data) { std::pair<int, int> key = {wd.year, wd.month}; monthlyTempMap[key].push_back(wd.temperature); } // 计算均值并插入BST for (const auto& entry : monthlyTempMap) { double mean = std::accumulate(entry.second.begin(), entry.second.end(), 0.0) / entry.second.size(); bst.insert(entry.first, mean); } return bst; }
需求b:指定年份各月份的气象属性平均值
构建以年份为键、月份→均值映射为值的BST:
BST<int, std::map<int, double>> buildYearlyMonthlyMeanBST(const std::vector<WeatherData>& data) { BST<int, std::map<int, double>> bst; std::map<int, std::map<int, std::vector<double>>> yearlyTempMap; // 按年→月分组原始数据 for (const auto& wd : data) { yearlyTempMap[wd.year][wd.month].push_back(wd.temperature); } // 计算每年各月均值并插入BST for (const auto& yearEntry : yearlyTempMap) { std::map<int, double> monthlyMeans; for (const auto& monthEntry : yearEntry.second) { double mean = std::accumulate(monthEntry.second.begin(), monthEntry.second.end(), 0.0) / monthEntry.second.size(); monthlyMeans[monthEntry.first] = mean; } bst.insert(yearEntry.first, monthlyMeans); } return bst; }
需求c:指定年份各月份的气象属性总值
逻辑和需求b几乎一致,只需把均值计算改为总和:
BST<int, std::map<int, double>> buildYearlyMonthlyTotalBST(const std::vector<WeatherData>& data) { BST<int, std::map<int, double>> bst; std::map<int, std::map<int, std::vector<double>>> yearlyTempMap; for (const auto& wd : data) { yearlyTempMap[wd.year][wd.month].push_back(wd.temperature); } for (const auto& yearEntry : yearlyTempMap) { std::map<int, double> monthlyTotals; for (const auto& monthEntry : yearEntry.second) { double total = std::accumulate(monthEntry.second.begin(), monthEntry.second.end(), 0.0); monthlyTotals[monthEntry.first] = total; } bst.insert(yearEntry.first, monthlyTotals); } return bst; }
3. 整合原有气象计算功能
基于BST实现四种需求的交互逻辑:
// 需求a:查询指定年月的均值 void queryMonthlyMean(BST<std::pair<int, int>, double>& bst, int year, int month) { auto node = bst.search({year, month}); if (node) { std::cout << "[" << year << "-" << month << "] 温度平均值:" << node->value << std::endl; } else { std::cout << "该年月无数据记录" << std::endl; } } // 需求b:查询指定年份各月均值 void queryYearlyMonthlyMean(BST<int, std::map<int, double>>& bst, int year) { auto node = bst.search(year); if (!node) { std::cout << "该年份无数据记录" << std::endl; return; } std::cout << year << "年各月温度平均值:" << std::endl; for (const auto& entry : node->value) { std::cout << " " << entry.first << "月:" << entry.second << std::endl; } } // 需求d:导出指定年份各月均值到CSV void exportYearlyMeanToCSV(BST<int, std::map<int, double>>& bst, int year, const std::string& filename) { auto node = bst.search(year); if (!node) { std::cout << "该年份无数据记录" << std::endl; return; } std::ofstream csvFile(filename); csvFile << "月份,温度平均值\n"; for (const auto& entry : node->value) { csvFile << entry.first << "," << entry.second << "\n"; } std::cout << "CSV文件已导出至:" << filename << std::endl; }
4. 关键细节与优化点
- 键的比较逻辑:用
std::pair<int,int>作为年月键时,C++默认按年→月的顺序比较,正好符合时间排序需求,无需自定义比较运算符。 - 内存管理:BST类的析构函数实现了递归销毁节点,避免内存泄漏。
- 效率优化:5万行数据量级下,BST的O(log n)查找/插入效率完全够用;如果后续数据量大幅增长,可考虑平衡BST(如AVL树、红黑树),但当前需求无需过度设计。
- 扩展性:模板BST支持任意键值类型,后续新增气象属性或统计维度时,只需复用现有BST结构,修改数据分组逻辑即可。
内容的提问来源于stack exchange,提问作者Aashish Pandav
相关产品推荐
相关产品推荐

