首页 新闻 工控搜 论坛 厂商论坛 产品 方案 厂商 人才 文摘 下载 展览
中华工控网首页
  P L C | 变频器与传动 | 传感器 | 现场检测仪表 | 工控软件 | 人机界面 | 运动控制
  D C S | 工业以太网 | 现场总线 | 显示调节仪表 | 数据采集 | 数传测控 | 工业安全
  电 源 | 嵌入式系统 | PC based | 机柜箱体壳体 | 低压电器 | 机器视觉
函数递归在树形结构数据遍历中的应用
紫金桥软件技术有限公司
收藏本文     查看收藏
 

       我们在使用树形结构数据时,常常需要遍历整棵树或某一支下的所有结点,用于查找、打印等功能。因为树形结构不同于数组、链表等简单数据结构,它像树枝一样每个根结点可以具有多个子结点,无限延展,因此需要专门的算法去遍历。树形结构的遍历有很多种方法,下面我们以紫金桥监控组态软件(以下简称为“RealInfo)为例,简单讲解函数递归在这种遍历方法中的应用。

       RealInfo中,“树形控件”是表示树状结构数据的组件,“自由报表”是表示表格数据的组件,这两种组件自身都提供了一些常用方法。我们现在实现这样的功能:将树形控件中的指定分支数据打印在自由报表中。可以利用窗口自定义函数的递归功能。

       树形控件中的数据显示方式如下图所示:

       每个结点以结点编码为唯一标识,每个结点可以显示一个字符串作为结点文本(详见RealInfo联机帮助)。

       本例中,我们将树形结构数据打印在自由报表上,其效果如下图所示:

       每个根结点打印完成后,遇到子结点时打印位置自动向右、向下移动一个单元格;遇到兄弟结点时打印位置向下移动一个单元格。

       现在我们开始分析算法。我们知道,树的遍历是指沿着某条搜索路线,依次对树中每个结点均做一次且仅做一次访问。这样,我们把遍历过程想象成为一次单程旅行,出发点是树的根结点,然后按先自左向右、然后自上而下的顺序,先后经过每个结点,最后走到最下方的叶子结点处。

我们可以采用这样的遍历方式:

1)        当所在结点具有子结点时,那么按自左向右原则,接着访问它的第一个子结点,直到所在结点没有子结点为止。

2)        当所在结点没有子结点,但具有兄弟结点时,那么按自上向下原则依次访问它的兄弟结点。

3)        当所在结点没有子结点,而且没有兄弟结点时,那么按自上向下原则访问它父结点的兄弟结点。

分析这个过程并观察树形结构,我们会发现,每个父结点可以拥有n(n>=0)个子结点,若将这n个子结点看作父结点,则每个父结点仍然具有n个子结点。由此看来,每一支数据乃至整棵树都可以看作是有限个父-子结构的组合。在树的遍历过程中,总是不断的重复“父→子”这一访问方式,因此我们可以提取这一方式形成一个函数,并利用函数递归来完成整个遍历。

这个函数用于根据输入的父结点编码和起始打印位置将其所有子结点打印出来。算法如下:

       函数首先判断输入结点是否具有子结点,如果没有则返回,如果有则取得子结点列表,然后循环打印每个子结点并递归调用自身函数打印其子结点,当一个结点a的子结点打印完毕并返回后按相同规则依次打印的a结点的兄弟结点,直到所有兄弟结点打印完毕为止。

       工程制作过程如下:

1)        新建窗口,创建树形控件,起名为“tree”;创建自由报表起名为“report”;创建一个按钮。

2)        创建窗口函数(用于得到指定结点的子结点编码数组):

func_GetAllChildNodeKey(Tree& treeObj, String& strFatherNodeKey, String Array& strArrChildNodeKeys) As Int

代码如下:

int nChildNodeCount = 0;

string strNodeKeyTemp = "";

int i = 0;

strArrChildNodeKeys.Clear();

nChildNodeCount = #treeObj.GetNodeCount(strFatherNodeKey);

for i=0 to nChildNodeCount

       if strFatherNodeKey=="" then

              strNodeKeyTemp = IntToStr(i,10);

       else

              strNodeKeyTemp = strFatherNodeKey + "." + IntToStr(i,10);

       endif

       strArrChildNodeKeys.Add(strNodeKeyTemp);

next

return nChildNodeCount;

3)        创建窗口函数(用于递归打印指定结点的子结点,不打印自身结点)

func_PrintToReport(String strFatherNodeKey, Int nCol, Int nRow, Int& nRowOffSet) As Int

代码如下:

string strArrChildNodeKeys[];

string strNodeText = "";

int nCount = 0;

int i = 0;

func_GetAllChildNodeKey(#tree,strFatherNodeKey,strArrChildNodeKeys);

nCount = strArrChildNodeKeys.GetCount();

if nCount>0 then

       if #report.ColCount()<nCol then

              #report.AddCol(1);

       endif

       for i=0 to nCount

              if #report.RowCount()<nRow+nRowOffset then

                     #report.AddRow(1);

              endif

             

              strNodeText = #tree.GetNodeTxt(strArrChildNodeKeys[i]);       //打印本结点

              #report.SetTxt(nCol,nRow+nRowOffset,strNodeText);

              nRowOffset = nRowOffset + 1;

              nRowOffset = func_PrintToReport(strArrChildNodeKeys[i]

,nCol+1,nRow,nRowOffset); //递归

       next

endif

return nRowOffset;

4)        创建窗口函数(用于打印初始结点自身,并启动递归函数):func_Print()

代码如下

int nRowOffSet = 0;

#report.DelTailCol(#report.ColCount());

#report.DelTailRow(#report.RowCount());

#report.AddCol(1);

#report.AddRow(1);

#report.SetTxt(1,1,#tree.GetNodeTxt(#tree.GetCurSelNodeKey()));

func_PrintToReport(#tree.GetCurSelNodeKey(),2,2,nRowOffSet);

5)        在按钮中鼠标点击动作中输入:func_Print();

6)        运行并查看效果。运行时,不选择树结点,点击按钮后报表中打印出整棵树,因为根结点文本为空,所以报表第一列为空。选中任意一个树结点后,报表中打印出本分支所有结点,包含本结点。

效果图如下:

       本文以RealInfo为例,讲述了一种通过函数递归调用来实现树形结构数据遍历的方法,其中递归函数体实现了打印指定结点的子结点功能。本方法适用于少量树形结构数据的遍历,当数据量过大时需要作进一步优化。


 

状 态: 离线

公司简介
产品目录

公司名称: 紫金桥软件技术有限公司
联 系 人: 李磊
电  话: 0459-8151391-808
传  真: 0459-8151391-804
地  址: 大庆市高新区服务外包产业园C-1座817室
邮  编: 163316
主  页:
 
该厂商相关技术文摘:
跨平台实时数据库变量引用导航功能介绍
跨平台实时数据库 如何利用MODBUS仿真软件测试MODBUS驱动
紫金桥跨平台实时数据库如何实现多屏显示
紫金桥跨平台软实时数据库Web服务器和数据服务器分离访问的配置
紫金桥跨平台软件远程采集RealInfo6.5
使用虚拟机做的工程实现跨网Web访问
紫金桥软件Microsoft Office Access 2003的ODBC数据源配置
紫金桥软件闸门整体自动化监控系统
通过紫金桥软件来提高画面组态速度
组态软件在配套设备中的应用
紫金桥的关系库同步工具简介
紫金桥组态软件与欧姆龙PLC以太网通信(FINS命令)——CPU型号-CJ2M-CPU33
更多文摘...
立即发送询问信息在线联系该技术文摘厂商:
用户名: 密码: 免费注册为中华工控网会员
请留下您的有效联系方式,以方便我们及时与您联络

关于我们 | 联系我们 | 广告服务 | 本站动态 | 友情链接 | 法律声明 | 不良信息举报
工控网客服热线:0755-86369299
版权所有 中华工控网 Copyright©2022 Gkong.com, All Rights Reserved