主要存在几个地方需要注意:
1.数据结构的选择
struct Node {
//决策树节点
string attribute;//属性,下一个需要决策的属性值
string arrived_value;//选择什么样的属性值,到达的该结点!
vector<Node *> childs;//所有的孩子
Node() {
attribute = blank;
arrived_value = blank;
}
};
2.属性的选择即信息增益和熵的计算
3.递归遍历生成树
下面是源代码,参考代码后进行了修改,并增加了测试。
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <string>
#include <map>
#include <cmath>
#include <stack>
#include <queue>
using namespace std;
#define MAXLEN 6//输入每行的数据个数
//多叉树的实现
//1 广义表
//2 父指针表示法,适于经常找父结点的应用
//3 子女链表示法,适于经常找子结点的应用
//4 左长子,右兄弟表示法,实现比较麻烦
//5 每个结点的所有孩子用vector保存
//教训:数据结构的设计很重要,本算法采用5比较合适,同时
//注意维护剩余样例和剩余属性信息,建树时横向遍历考循环属性的值,
//纵向遍历靠递归调用
vector <vector <string> > state;//实例集
vector <vector <string> > state2;//实例集
vector<vector<string>> testdata;
vector <string> item(MAXLEN);//对应一行实例集
vector <string> attribute_row;//保存首行即属性行数据
string end("end");//输入结束
string yes("yes");
string no("no");
string blank("");
map<string, vector < string > > map_attribute_values;//存储属性对应的所有的值
int tree_size = 0;
struct Node {
//决策树节点
string attribute;//属性
string arrived_value;//到达的属性值
vector<Node *> childs;//所有的孩子
Node() {
attribute = blank;
arrived_value = blank;
}
};
Node * root;
//根据数据实例计算属性与值组成的map
void ComputeMapFrom2DVector() {
unsigned int i, j, k;
bool exited = false;
vector<string> values;
for (i = 1; i < MAXLEN - 1; i++) {
//按照列遍历
for (j = 1; j < state.size(); j++) {
for (k = 0; k < values.size(); k++) {
if (!values[k].compare(state[j][i])) exited = true;//value中是否存在。