1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
| #include <iostream> #include <vector> #include <string> #include <map> #include <cmath> #include <algorithm> #include <memory>
using namespace std;
using Data = vector<vector<string>>;
struct TreeNode { int feature_idx; string label; map<string, shared_ptr<TreeNode>> children; };
double entropy(const Data& data) { map<string, int> freq; for (const auto& row : data) { freq[row.back()]++; } double ent = 0.0; int total = data.size(); for (const auto& p : freq) { double prob = (double)p.second / total; ent -= prob * log2(prob); } return ent; }
map<string, Data> split_by_feature(const Data& data, int feature_idx) { map<string, Data> subsets; for (const auto& row : data) { string val = row[feature_idx]; subsets[val].push_back(row); } return subsets; }
double info_gain(const Data& data, int feature_idx) { double ent_before = entropy(data); auto subsets = split_by_feature(data, feature_idx); double ent_after = 0.0; int total = data.size(); for (const auto& pair : subsets) { double prob = (double)pair.second.size() / total; ent_after += prob * entropy(pair.second); } return ent_before - ent_after; }
int best_feature(const Data& data, const vector<int>& feature_indices) { int best_idx = -1; double best_gain = -1.0; for (int idx : feature_indices) { double gain = info_gain(data, idx); if (gain > best_gain) { best_gain = gain; best_idx = idx; } } return best_idx; }
bool all_same_class(const Data& data) { if (data.empty()) return true; const string& first = data[0].back(); for (size_t i = 1; i < data.size(); ++i) { if (data[i].back() != first) return false; } return true; }
shared_ptr<TreeNode> build_tree(const Data& data, const vector<int>& feature_indices) { auto node = make_shared<TreeNode>();
if (data.empty()) { node->feature_idx = -1; node->label = "Unknown"; return node; }
if (all_same_class(data)) { node->feature_idx = -1; node->label = data[0].back(); return node; }
if (feature_indices.empty()) { node->feature_idx = -1; map<string, int> freq; for (const auto& row : data) freq[row.back()]++; node->label = max_element(freq.begin(), freq.end(), [](const auto& a, const auto& b) { return a.second < b.second; })->first; return node; }
int best = best_feature(data, feature_indices); node->feature_idx = best;
auto subsets = split_by_feature(data, best);
vector<int> remaining_features; for (int idx : feature_indices) { if (idx != best) remaining_features.push_back(idx); }
for (const auto& pair : subsets) { const string& value = pair.first; const Data& subset_data = pair.second; node->children[value] = build_tree(subset_data, remaining_features); }
return node; }
string predict(const shared_ptr<TreeNode>& tree, const vector<string>& sample) { if (tree->feature_idx == -1) { return tree->label; } string feat_val = sample[tree->feature_idx]; auto it = tree->children.find(feat_val); if (it == tree->children.end()) { return "Unknown"; } return predict(it->second, sample); }
int main() { Data data = { {"Sunny", "Hot", "High", "False", "No"}, {"Sunny", "Hot", "High", "True", "No"}, {"Overcast", "Hot", "High", "False", "Yes"}, {"Rainy", "Mild", "High", "False", "Yes"}, {"Rainy", "Cool", "Normal", "False", "Yes"}, {"Rainy", "Cool", "Normal", "True", "No"}, {"Overcast", "Cool", "Normal", "True", "Yes"}, {"Sunny", "Mild", "High", "False", "No"}, {"Sunny", "Cool", "Normal", "False", "Yes"}, {"Rainy", "Mild", "Normal", "False", "Yes"}, {"Sunny", "Mild", "Normal", "True", "Yes"}, {"Overcast", "Mild", "High", "True", "Yes"}, {"Overcast", "Hot", "Normal", "False", "Yes"}, {"Rainy", "Mild", "High", "True", "No"} };
vector<int> feature_indices = {0, 1, 2, 3};
auto tree = build_tree(data, feature_indices);
vector<string> sample = {"Sunny", "Cool", "High", "False"}; string result = predict(tree, sample); cout << "预测结果: " << result << endl;
return 0; }
|