树类总体框架

本文介绍了一种基于树控件的数据管理系统设计方案,包括关键类如CTreeData、CDetailList等的功能与交互方式,以及数据的加载与卸载机制。

版权声明:可以任意转载,转载时请务必以超链接形式标明如下文章原始出处和作者信息及本声明

作者:xixi

出处:http://blog.youkuaiyun.com/slowgrace/archive/2009/04/20/4095915.aspx

本文来自这个帖子这个帖子这个帖子的讨论。

1、基本想法

(1)和树节点显示相关的数据载入对象模型,这些数据一部分在CTree的节点CNode里,一部分在CDetailList里的Detail结构里,与相应的数据表的设计相对应。

(2)当用户通过用户界面改动数据的时候,一杆子捅到底,直接到数据库里改,改完再到界面上显示出来。

(3)类之间消息的传递:通过一个全局的CMsgMate变量进行。
解释
(1)用类还是用结构,前面有个讨论。最后决定CNode用类,因为我看到的开源的扩充树类的代码都用了自己的Node类,我想这些前辈可能都是考虑过的,应该有它的道理;Detail用结构,这主要是心痒想试试zhao支的招,增加点见识。
(2)数据的变动没有像zhao建议的那样用内存标记。有2个原因,1则我觉得变动时我一般只操作有限的几个节点(常常是1个),所以这时候性能的差异估计可忽略;2则我还有细节子窗体用于显示细节相关的数据,有些数据在树模型里,有些不在,到时候一部分从内存取、一部分从树模型里取,还要保证数据一致性,感觉逻辑太复杂,维护性差。
要注意的
(1)尽量通过消息的传递而避免直接调用类的公用方法来解耦;
(2)在实现数据变动相关的方法时注意封装,注意考虑日后也许会想转到zhao的方法时的可替换性。

 

2、Classes

(1)CDetailList,缩写dlst。一个CDetailList对象对应一个细节表。它包含一个NODE_DETAIL类型的数组,每一个NODE_DETAIL结构对应一条细节记录。CDetailList对象初始化时会加载相应的细节表的所有数据。

(2)CTreeData,缩写trd。一个CTreeData对象对应一个节点表。它包含一个CNodeData对象的集合。CTreeData对象初始化时会加载相应的节点表的所有数据。

(3)CNodeData,缩写cnd。一个CNodeData对象对应一条节点记录。

(4)CTreeCtl,缩写trc。一个CTreeCtl对象对应一个treeview控件。它知道自己是属于哪个树窗,也知道自己表现的是哪个节点表的数据。

(5)CTreeWnd,缩写twd。 一个CTreeWnd对象对应一个树窗。所谓树窗,是指含有树控件的窗体。它含有用于显示细节的子窗体和listview,它懂得在树控件上的当前节点发生变化时,相应地调整自己的显示。它还负责一些罗嗦的初始化工作,像放置控件的位置、设置imagelist、设置event procedure、设置快捷菜单等。

(6)CDtlSfr:缩写cdf。一个CDtlSfr对象对应一个子窗体。

全局有个两个集合变量,一个是CDetailList的集合gcolDlsts,一个是CTreeData的集合gcolTrds。这也就是zhao一直以来所建议的“把数据放在内存里”的具体实现。大家要用数据的时候都去访问这两个集合。

除了上面的几个主要的类外,还有如下辅助类和模块:

(1)CMsgMate:用于发送自定义消息

(2)CTabStrip

(3)ChkCnd:这是一个测试类,专用于测试node相关数据的。

(4)basTree:树相关的全局函数。前面那两个集合变量,还有一些常数都在这里。

(5)basTest:测试相关的。生成随机数的一系列函数等。

(6)basAPI:API相关的一些声明。

 

3、数据的装载和卸载

细节表的数据是一次性的loaddetails,这需要每个窗体在load时都调用这个函数。这个函数会判断,如果details已经load就不重复load。当然也可以强制reload,只要把参数blnReload设为真就行。节点表的数据是用哪个load哪个,用GetTrd函数。这个函数也是会判断的,如果已经load就不重复load。

Unload的话,由CTreeWnd负责,如果系统内只剩一个CTreeWnd实例,那么它unload的时候就负责把所有detail和node数据卸载。

 

4、类间消息的传递

类间协作.jpg

如上图,gcmm是一个全局的CMsgMate对象。所有需要收发消息的类都含有一个指针指向gcmm,这样它们就可以互通有无了。比如,当一个CTreeData对象的数据发生变化时,它就通过gcmm发一个消息,说自己变了。剩下的是CTreeCtl响应它还是CTreeWnd响应它就都没关系,爱咋咋,反正我发了通知了。

详见:关于类间消息的探讨

更多树类文章

### 决策算法的框架结构及实现步骤 #### 一、决策算法的基本框架 决策是一种基于形结构的监督学习算法,其核心目标是通过对数据集进行递归划分,构建一棵能够高效分或回归的。整个框架可以分为以下几个部分: 1. **根节点初始化** 决策从一个包含所有样本的根节点开始,这些样本属于不同的别或具有连续的目标变量值[^1]。 2. **特征选择与分裂准则** 在每个内部节点处,选择最优特征及其对应的阈值来进行分割。常用的分裂标准包括信息增益(Information Gain)、基尼指数(Gini Index)等。对于分问题,通常使用熵作为衡量不纯度的标准;而对于回归问题,则常采用均方误差或其他统计量来指导最佳切分点的选择[^2]。 3. **子节点扩展** 根据选定的最佳特征和阈值,将当前节点划分为多个子节点。这一过程会重复执行直到满足停止条件为止。 4. **终止条件判断** 当某个节点内的样本完全同质(即属于同一),或者无法继续找到有效的切割方式时,该分支便结束生长成为叶节点。此外还可以设置最大深度、最小样本数等超参数控制的增长程度以防过拟合现象发生[^3]。 5. **叶子结点标记** 对于每一个到达终点状态下的分区集合赋予相应的标签表示预测结果——如果是分任务则给出多数投票决定所属别;若是回归任务则是平均响应值得出估计数值。 --- #### 二、决策的具体实现步骤 以下是构建一颗完整决策的主要操作流程: 1. **输入准备** - 准备训练数据集 \(D\) ,其中包含若干条记录 \((x_i, y_i)\),\(x_i\) 表示属性向量,\(y_i\) 则为目标变量。 2. **初始化** - 创建初始节点 N 并将其设为根节点 RootNode[]. 3. **循环迭代直至收敛** - 如果当前节点的数据集中仅存在单一别实例或是达到了预定的最大高度限制,则直接返回此节点作为一个终端单元并标注相应输出值; - 否则,计算各个候选特性相对于现有群体的信息收益情况,并选取使得总体不确定性下降幅度最大的那个维度 k* 及对应临界位置 t*; - 使用上述选出的关键要素把原始组细分成两个互斥且穷尽的新子群 S_left 和 S_right ; - 分别针对这两个新生支路调用相同逻辑再次展开深入探索直至全部路径都已闭合完毕。 4. **后处理调整(可选)** - 实施必要的修剪措施减少泛化错误风险,例如成本复杂度削减法(CCPT). --- ```python from sklearn.tree import DecisionTreeClassifier import numpy as np # 示例代码:创建简单的决策模型 def build_decision_tree(X_train, y_train): """ 构建决策器 参数: X_train (numpy.ndarray): 训练数据特征矩阵 y_train (numpy.ndarray): 训练数据标签数组 返回: model (DecisionTreeClassifier): 已经训练好的决策模型 """ # 初始化决策器,默认使用CART算法 clf = DecisionTreeClassifier(criterion='entropy', max_depth=None) # 拟合训练数据 clf.fit(X_train, y_train) return clf if __name__ == "__main__": # 假定我们有如下二维特征空间和平面坐标系上的离散别分布 X = np.array([[0, 0], [1, 1]]) y = np.array([0, 1]) tree_model = build_decision_tree(X, y) ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值