用c++写一个西瓜数据集的决策树

时间: 2024-05-14 18:19:11 浏览: 12
好的,下面是一个简单的C++代码实现西瓜数据集的决策树: ```c++ #include <iostream> #include <vector> #include <string> #include <map> #include <math.h> using namespace std; // 定义数据结构 struct Sample { int index; bool color; // 0: green, 1: yellow double root; // 0: curl, 1: little-curl, 2: straight double knocks; bool texture; // 0: clear, 1: a little blurriness bool navel; // 0: yes, 1: no double touch; // 0: hard, 1: a little soft, 2: soft bool good; // 0: bad, 1: good }; // 定义数据集 vector<Sample> dataset = { {1, 0, 0, 0.697, 0, 0, 0.460, 0}, {2, 0, 0, 0.774, 0, 0, 0.376, 0}, {3, 0, 0, 0.634, 0, 0, 0.264, 0}, {4, 0, 0, 0.608, 0, 0, 0.318, 0}, {5, 0, 0, 0.556, 0, 0, 0.215, 0}, {6, 0, 1, 0.403, 0, 0, 0.237, 0}, {7, 0, 1, 0.481, 0, 0, 0.149, 0}, {8, 0, 1, 0.437, 0, 0, 0.211, 0}, {9, 0, 1, 0.666, 0, 0, 0.091, 1}, {10, 0, 1, 0.243, 0, 0, 0.267, 1}, {11, 1, 0, 0.245, 0, 1, 0.057, 1}, {12, 1, 0, 0.343, 0, 1, 0.099, 1}, {13, 1, 0, 0.639, 0, 1, 0.161, 1}, {14, 1, 0, 0.657, 0, 1, 0.198, 1}, {15, 1, 0, 0.360, 0, 1, 0.370, 1}, {16, 1, 1, 0.593, 0, 1, 0.042, 1}, {17, 1, 1, 0.719, 0, 1, 0.103, 1}, {18, 1, 1, 0.359, 0, 1, 0.188, 1}, {19, 1, 1, 0.339, 0, 1, 0.241, 1}, {20, 1, 1, 0.282, 0, 1, 0.257, 1}, {21, 1, 1, 0.748, 1, 0, 0.232, 0}, {22, 1, 1, 0.714, 1, 0, 0.346, 0}, {23, 1, 1, 0.483, 1, 0, 0.312, 0}, {24, 1, 1, 0.478, 1, 0, 0.437, 0}, {25, 1, 1, 0.525, 1, 0, 0.369, 0}, {26, 1, 1, 0.751, 1, 1, 0.315, 0}, {27, 1, 0, 0.532, 1, 1, 0.253, 0}, {28, 1, 0, 0.473, 1, 1, 0.214, 0}, {29, 1, 0, 0.725, 1, 1, 0.267, 0}, {30, 1, 0, 0.446, 1, 1, 0.057, 0} }; // 定义决策树结点 struct TreeNode { int feature; // 当前结点选择的特征 double threshold; // 当前结点选择的阈值 bool leaf; // 是否为叶子结点 bool result; // 叶子结点的预测结果 TreeNode *left; // 左子树 TreeNode *right; // 右子树 }; // 计算熵 double entropy(int count_good, int count_bad) { double p_good = (double)count_good / (double)(count_good + count_bad); double p_bad = (double)count_bad / (double)(count_good + count_bad); if (p_good == 0 || p_bad == 0) { return 0; } return -p_good * log2(p_good) - p_bad * log2(p_bad); } // 计算数据集在某个特征上的条件熵 double conditional_entropy(vector<Sample> samples, int feature_index, double threshold, int &count_left_good, int &count_left_bad, int &count_right_good, int &count_right_bad) { count_left_good = count_left_bad = count_right_good = count_right_bad = 0; for (Sample sample : samples) { if (sample.good) { if (sample.index <= threshold) { count_left_good++; } else { count_right_good++; } } else { if (sample.index <= threshold) { count_left_bad++; } else { count_right_bad++; } } } double p_left = (double)(count_left_good + count_left_bad) / (double)samples.size(); double p_right = (double)(count_right_good + count_right_bad) / (double)samples.size(); return p_left * entropy(count_left_good, count_left_bad) + p_right * entropy(count_right_good, count_right_bad); } // 选择最优特征和阈值 void choose_best_feature(vector<Sample> samples, int &best_feature_index, double &best_threshold) { double min_entropy = 1e9; int best_count_left_good, best_count_left_bad, best_count_right_good, best_count_right_bad; for (int i = 0; i < 6; i++) { double min_value = 1e9, max_value = -1e9; for (Sample sample : samples) { if (sample.feature(i) < min_value) { min_value = sample.feature(i); } if (sample.feature(i) > max_value) { max_value = sample.feature(i); } } for (double threshold = min_value; threshold <= max_value; threshold += 0.1) { int count_left_good, count_left_bad, count_right_good, count_right_bad; double current_entropy = conditional_entropy(samples, i, threshold, count_left_good, count_left_bad, count_right_good, count_right_bad); if (current_entropy < min_entropy) { min_entropy = current_entropy; best_feature_index = i; best_threshold = threshold; best_count_left_good = count_left_good; best_count_left_bad = count_left_bad; best_count_right_good = count_right_good; best_count_right_bad = count_right_bad; } } } } // 构建决策树 TreeNode* build_decision_tree(vector<Sample> samples) { // 如果所有样本都属于同一类别,则直接返回 bool all_good = true, all_bad = true; for (Sample sample : samples) { if (sample.good) { all_bad = false; } else { all_good = false; } } if (all_good) { TreeNode *node = new TreeNode(); node->leaf = true; node->result = true; return node; } if (all_bad) { TreeNode *node = new TreeNode(); node->leaf = true; node->result = false; return node; } // 选择最优特征和阈值 int best_feature_index; double best_threshold; choose_best_feature(samples, best_feature_index, best_threshold); // 构建子树 TreeNode *node = new TreeNode(); node->feature = best_feature_index; node->threshold = best_threshold; node->left = build_decision_tree(vector<Sample>(samples.begin(), samples.begin() + best_count_left_good + best_count_left_bad)); node->right = build_decision_tree(vector<Sample>(samples.begin() + best_count_left_good + best_count_left_bad, samples.end())); return node; } // 预测样本的类别 bool predict(TreeNode *node, Sample sample) { if (node->leaf) { return node->result; } if (sample.feature(node->feature) <= node->threshold) { return predict(node->left, sample); } else { return predict(node->right, sample); } } int main() { // 构建决策树 TreeNode *root = build_decision_tree(dataset); // 预测样本的类别 Sample sample = {31, 1, 0, 0.697, 1, 1, 0.460, 0}; bool result = predict(root, sample); cout << (result ? "Good" : "Bad") << endl; // 释放决策树 delete root; return 0; } ``` 这是一个简单的实现,可能存在一些性能问题和不足之处,但可以作为一个基础的参考。

相关推荐

最新推荐

recommend-type

C/C++读写注册表中二进制数据(代码示例)

主要介绍了使用Windows API 函数中的RegOpenKeyEx()函数和RegSetValueEx()函数来实现对注册表某项写入二进制键值,需要的朋友可以参考下
recommend-type

linux系统中c++写日志文件功能分享

主要介绍了linux系统中c++写日志文件功能,简化了glog,只保留了写日志文件的功能,只是改写了linux版本,需要的朋友可以参考下
recommend-type

C++如何判断一个数字是否为质数

主要为大家详细介绍了C++如何判断一个数字是否为质数,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

C++数据结构与算法之双缓存队列实现方法详解

主要介绍了C++数据结构与算法之双缓存队列实现方法,结合实例形式分析了双缓存队列的原理、实现方法与相关注意事项,需要的朋友可以参考下
recommend-type

C++实现哈夫曼树简单创建与遍历的方法

主要介绍了C++实现哈夫曼树简单创建与遍历的方法,对于C++算法的学习来说不失为一个很好的借鉴实例,需要的朋友可以参考下
recommend-type

zigbee-cluster-library-specification

最新的zigbee-cluster-library-specification说明文档。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

MATLAB柱状图在信号处理中的应用:可视化信号特征和频谱分析

![matlab画柱状图](https://img-blog.csdnimg.cn/3f32348f1c9c4481a6f5931993732f97.png) # 1. MATLAB柱状图概述** MATLAB柱状图是一种图形化工具,用于可视化数据中不同类别或组的分布情况。它通过绘制垂直条形来表示每个类别或组中的数据值。柱状图在信号处理中广泛用于可视化信号特征和进行频谱分析。 柱状图的优点在于其简单易懂,能够直观地展示数据分布。在信号处理中,柱状图可以帮助工程师识别信号中的模式、趋势和异常情况,从而为信号分析和处理提供有价值的见解。 # 2. 柱状图在信号处理中的应用 柱状图在信号处理
recommend-type

hive中 的Metastore

Hive中的Metastore是一个关键的组件,它用于存储和管理Hive中的元数据。这些元数据包括表名、列名、表的数据类型、分区信息、表的存储位置等信息。Hive的查询和分析都需要Metastore来管理和访问这些元数据。 Metastore可以使用不同的后端存储来存储元数据,例如MySQL、PostgreSQL、Oracle等关系型数据库,或者Hadoop分布式文件系统中的HDFS。Metastore还提供了API,使得开发人员可以通过编程方式访问元数据。 Metastore的另一个重要功能是跟踪表的版本和历史。当用户对表进行更改时,Metastore会记录这些更改,并且可以让用户回滚到
recommend-type

JSBSim Reference Manual

JSBSim参考手册,其中包含JSBSim简介,JSBSim配置文件xml的编写语法,编程手册以及一些应用实例等。其中有部分内容还没有写完,估计有生之年很难看到完整版了,但是内容还是很有参考价值的。