用c++写一个判断西瓜好坏的决策树代码,并附上注释和训练数据

时间: 2023-06-15 08:04:42 浏览: 53
好的,下面是C++代码实现: ```c++ #include <iostream> using namespace std; // 定义西瓜的属性结构体 struct Watermelon { int color; // 颜色,0代表青绿,1代表乌黑,2代表浅白 float root; // 根蒂,0代表蜷缩,1代表稍蜷,2代表硬挺 float sound; // 敲声,0代表沉闷,1代表浊响,2代表清脆 int good; // 是否好瓜,0代表否,1代表是 }; // 定义训练数据 Watermelon train_data[] = { {0, 0, 0, 0}, {0, 0, 1, 0}, {1, 0, 1, 1}, {2, 0, 1, 1}, {2, 1, 0, 1}, {2, 2, 1, 0}, {1, 1, 0, 1}, {0, 2, 1, 0}, {0, 1, 0, 1}, {2, 1, 1, 1}, {0, 1, 1, 1}, {1, 0, 0, 0}, {1, 1, 1, 1}, {2, 1, 0, 0} }; // 计算数据集中好瓜和坏瓜的个数 void count_good_bad(Watermelon *data, int len, int &good, int &bad) { good = 0; bad = 0; for (int i = 0; i < len; i++) { if (data[i].good == 1) { good++; } else { bad++; } } } // 计算数据集中给定属性的某个值的好瓜和坏瓜的个数 void count_good_bad_by_attr(Watermelon *data, int len, int attr, float value, int &good, int &bad) { good = 0; bad = 0; for (int i = 0; i < len; i++) { if (data[i].good == 1 && data[i].color == value) { good++; } else if (data[i].good == 0 && data[i].color == value) { bad++; } } } // 计算数据集中给定两个属性的某个值的好瓜和坏瓜的个数 void count_good_bad_by_attr(Watermelon *data, int len, int attr1, float value1, int attr2, float value2, int &good, int &bad) { good = 0; bad = 0; for (int i = 0; i < len; i++) { if (data[i].good == 1 && data[i].color == value1 && data[i].root == value2) { good++; } else if (data[i].good == 0 && data[i].color == value1 && data[i].root == value2) { bad++; } } } // 计算数据集中给定三个属性的某个值的好瓜和坏瓜的个数 void count_good_bad_by_attr(Watermelon *data, int len, int attr1, float value1, int attr2, float value2, int attr3, float value3, int &good, int &bad) { good = 0; bad = 0; for (int i = 0; i < len; i++) { if (data[i].good == 1 && data[i].color == value1 && data[i].root == value2 && data[i].sound == value3) { good++; } else if (data[i].good == 0 && data[i].color == value1 && data[i].root == value2 && data[i].sound == value3) { bad++; } } } // 训练决策树 void train_decision_tree(Watermelon *data, int len, int depth) { int good, bad; count_good_bad(data, len, good, bad); if (good == 0 || bad == 0) { if (good == 0) { cout << "这是个坏瓜" << endl; } else { cout << "这是个好瓜" << endl; } return; } if (depth == 0) { if (good > bad) { cout << "这是个好瓜" << endl; } else { cout << "这是个坏瓜" << endl; } return; } // 选择最优属性 float info_gain, max_info_gain = -1; int best_attr = -1; for (int i = 0; i < 3; i++) { int num_values; float values[3]; if (i == 0) { num_values = 3; values[0] = 0; values[1] = 1; values[2] = 2; } else { num_values = 2; values[0] = 0; values[1] = 1; } for (int j = 0; j < num_values; j++) { int temp_good, temp_bad; if (i == 0) { count_good_bad_by_attr(data, len, i, values[j], temp_good, temp_bad); } else if (i == 1) { count_good_bad_by_attr(data, len, i, values[j], 2, 0, temp_good, temp_bad); } else { count_good_bad_by_attr(data, len, i, values[j], 0, 0, 1, 1, temp_good, temp_bad); } float p_good = (float)temp_good / (float)(temp_good + temp_bad); float p_bad = (float)temp_bad / (float)(temp_good + temp_bad); float temp_info_gain = -p_good * log2(p_good) - p_bad * log2(p_bad); if (temp_info_gain > max_info_gain) { max_info_gain = temp_info_gain; best_attr = i; } } } // 根据最优属性划分子数据集并递归训练 if (best_attr == 0) { int num_values = 3; float values[3]; values[0] = 0; values[1] = 1; values[2] = 2; for (int j = 0; j < num_values; j++) { int temp_good, temp_bad; count_good_bad_by_attr(data, len, best_attr, values[j], temp_good, temp_bad); cout << "如果颜色是" << values[j] << ":"; if (temp_good == 0 || temp_bad == 0) { if (temp_good == 0) { cout << "这是个坏瓜" << endl; } else { cout << "这是个好瓜" << endl; } } else { Watermelon *sub_data = new Watermelon[temp_good + temp_bad]; int index = 0; for (int k = 0; k < len; k++) { if (data[k].color == values[j]) { sub_data[index++] = data[k]; } } train_decision_tree(sub_data, index, depth - 1); } } } else if (best_attr == 1) { int num_values = 2; float values[2]; values[0] = 0; values[1] = 1; for (int j = 0; j < num_values; j++) { int temp_good, temp_bad; count_good_bad_by_attr(data, len, best_attr, values[j], 2, 0, temp_good, temp_bad); cout << "如果根蒂是" << values[j] << ":"; if (temp_good == 0 || temp_bad == 0) { if (temp_good == 0) { cout << "这是个坏瓜" << endl; } else { cout << "这是个好瓜" << endl; } } else { Watermelon *sub_data = new Watermelon[temp_good + temp_bad]; int index = 0; for (int k = 0; k < len; k++) { if (data[k].root == values[j]) { sub_data[index++] = data[k]; } } train_decision_tree(sub_data, index, depth - 1); } } } else { int num_values = 2; float values[2]; values[0] = 0; values[1] = 1; for (int j = 0; j < num_values; j++) { int temp_good, temp_bad; count_good_bad_by_attr(data, len, best_attr, values[j], 0, 0, 1, 1, temp_good, temp_bad); cout << "如果敲声是" << values[j] << ":"; if (temp_good == 0 || temp_bad == 0) { if (temp_good == 0) { cout << "这是个坏瓜" << endl; } else { cout << "这是个好瓜" << endl; } } else { Watermelon *sub_data = new Watermelon[temp_good + temp_bad]; int index = 0; for (int k = 0; k < len; k++) { if (data[k].sound == values[j]) { sub_data[index++] = data[k]; } } train_decision_tree(sub_data, index, depth - 1); } } } } int main() { train_decision_tree(train_data, 14, 3); return 0; } ``` 训练数据如下: ``` 颜色 根蒂 敲声 是否好瓜 0 0 0 0 0 0 1 0 1 0 1 1 2 0 1 1 2 1 0 1 2 2 1 0 1 1 0 1 0 2 1 0 0 1 0 1 2 1 1 1 0 1 1 1 1 0 0 0 1 1 1 1 2 1 0 0 ``` 其中,颜色属性的值为0代表青绿,1代表乌黑,2代表浅白;根蒂属性的值为0代表蜷缩,1代表稍蜷,2代表硬挺;敲声属性的值为0代表沉闷,1代表浊响,2代表清脆;是否好瓜属性的值为0代表否,1代表是。

相关推荐

最新推荐

recommend-type

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

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

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

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

C++实现两个有序数组的合并

主要为大家详细介绍了C++实现两个有序数组的合并,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

C++使用递归和非递归算法实现的二叉树叶子节点个数计算方法

主要介绍了C++使用递归和非递归算法实现的二叉树叶子节点个数计算方法,涉及C++二叉树的定义、遍历、统计相关操作技巧,需要的朋友可以参考下
recommend-type

C++使用Kruskal和Prim算法实现最小生成树

主要介绍了C++使用Kruskal和Prim算法实现最小生成树,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
recommend-type

STC89C51 简单时钟

STC89C51 简单时钟,叫你从基础开始学习单片机,
recommend-type

管理建模和仿真的文件

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

MATLAB归一化方法大比拼:5种方法,哪种最适合你的数据?

![MATLAB归一化方法大比拼:5种方法,哪种最适合你的数据?](https://www.finebi.com/wp-content/uploads/2019/11/FineBI%E8%A1%8C%E4%B8%9A%E9%A9%BE%E9%A9%B6%E8%88%B1-1024x510.png) # 1. MATLAB归一化概述 归一化是一种数据预处理技术,用于将数据缩放到特定范围内,从而消除不同特征之间的尺度差异。在MATLAB中,有各种归一化方法可用于不同类型的数据和应用程序。 归一化的主要目的是: - 提高模型的训练效率和准确性,通过消除特征之间的尺度差异,使模型能够更有效地学习
recommend-type

failed to register layer: ApplyLayer exit status 1 stdout: stderr: archive/tar: invalid tar header

很抱歉听到这个问题。这个错误通常是由于Docker镜像损坏或Docker存储库中缺少所需的图层引起的。您可以尝试以下几种方法来解决这个问题: 1. 清理Docker镜像和容器:使用命令“docker system prune”清理不再使用的Docker对象。 2. 检查Docker存储库:确保您正在使用可靠的Docker存储库,并检查是否存在所有必需的图层。 3. 重新下载Docker镜像:如果您确定问题是由于损坏的Docker镜像引起的,则可以尝试重新下载Docker镜像。 4. 更新Docker版本:如果您使用的是旧版Docker,则可能会出现此问题。尝试更新到最新版本的Docke
recommend-type

Linux系统常用操作命令大全手册

附件是Linux系统常用操作命令大全手册,是 markdown格式,其中覆盖了Linux系统管理、文件操作、网络配置等多个方面,都是日常工作中非常常用的命令,欢迎大家下载学习使用!