封装一个通用递归算法,使用TreeIterator和TreeMap来简化你的开发工作。
2013-10-22 21:38
387 查看
在实际工作中,你肯定会经常的对树进行遍历,并在树和集合之间相互转换,你会频繁的使用递归。
事实上,这些算法在逻辑上都是一样的,因此可以抽象出一个通用的算法来简化工作。
在这篇文章里,我向你介绍,我封装的两个类,TreeIterator和TreeMap,使用他们,你不必再写递归就可以在任意的树和任意的集合之间相互装换。
一 TreeIterator
1.1 TreeIterator功能描述:
TreeIterator封装了对树的遍历算法,他提供了如下功能:
1)遍历树
2)将任意一颗树转换为一个任意集合。
使用TreeIterator只需要一个方法调用就可以完成树的遍历,或者将树映射到一个集合,譬如,你可以使用TreeIterator方便的对一个dom进行遍历,或者将其导出到一个集合中,期间你可以将dom节点自由的映射到任意一个自定义对象。
1.2 TreeIterator优点:
不必再手写递归来遍历树,在实际工作中,这可以极大的节省你的时间,因为在写递归的时候,会经常忽略递归条件而造成死递归。
1.3 TreeIterator缺点:
TreeIterator内部使用了递归,所以会影响到性能。其次,第一次使用TreeIterator时,需要适应一下,一旦使用了几次,你会发现他确实可以减少你的工作量。
1.4 TreeIterator的设计思路:
在实际项目中,可能经常的要对一颗树进行遍历,然后将其导出到一个集合中,通常的做法是手写一个递归。然而,细心一点就会发现,这些递归操作的逻辑大部分都是相同的, 首先,都要获取根节点的所有子节点,然后递归的遍历每一个子节点,并将每一个子节点映射到一个自定义对象中。伪代码如下:
事实上,完全可以将这些重复的逻辑封装起来,然而要想做到一个通用的封住算法,需要解决如下几个问题:
1.如何获取当前节点的子节点。
2.将这个子节点映射到什么类型的对象。
这两个问题都是一个变化点,需要将他们留给使用者来做,因此可以使用委托来将这两个变化点提取成一个参数,这样,就可以让使用者来返回子节点以及将子节点映射到什么类型。
1.5 TreeIterator的完整代码:
View Code
事实上,这些算法在逻辑上都是一样的,因此可以抽象出一个通用的算法来简化工作。
在这篇文章里,我向你介绍,我封装的两个类,TreeIterator和TreeMap,使用他们,你不必再写递归就可以在任意的树和任意的集合之间相互装换。
一 TreeIterator
1.1 TreeIterator功能描述:
TreeIterator封装了对树的遍历算法,他提供了如下功能:
1)遍历树
2)将任意一颗树转换为一个任意集合。
使用TreeIterator只需要一个方法调用就可以完成树的遍历,或者将树映射到一个集合,譬如,你可以使用TreeIterator方便的对一个dom进行遍历,或者将其导出到一个集合中,期间你可以将dom节点自由的映射到任意一个自定义对象。
1.2 TreeIterator优点:
不必再手写递归来遍历树,在实际工作中,这可以极大的节省你的时间,因为在写递归的时候,会经常忽略递归条件而造成死递归。
1.3 TreeIterator缺点:
TreeIterator内部使用了递归,所以会影响到性能。其次,第一次使用TreeIterator时,需要适应一下,一旦使用了几次,你会发现他确实可以减少你的工作量。
1.4 TreeIterator的设计思路:
在实际项目中,可能经常的要对一颗树进行遍历,然后将其导出到一个集合中,通常的做法是手写一个递归。然而,细心一点就会发现,这些递归操作的逻辑大部分都是相同的, 首先,都要获取根节点的所有子节点,然后递归的遍历每一个子节点,并将每一个子节点映射到一个自定义对象中。伪代码如下:
public void Each(currentNode){ childNodesOfCurrentNode=get child nodes of currentNode;//获取当前节点的所有子节点。 foreach(var eachElement in childNodesOfCurrentNode){ Map(eachElement,target);//将当前子节点映射到target对象中 Each(eachElement);//然后对每一个子节点递归遍历。 } }
事实上,完全可以将这些重复的逻辑封装起来,然而要想做到一个通用的封住算法,需要解决如下几个问题:
1.如何获取当前节点的子节点。
2.将这个子节点映射到什么类型的对象。
这两个问题都是一个变化点,需要将他们留给使用者来做,因此可以使用委托来将这两个变化点提取成一个参数,这样,就可以让使用者来返回子节点以及将子节点映射到什么类型。
1.5 TreeIterator的完整代码:
class Area{ public int Id{get;set;} public string Name{get;set;} public int PId{get;set;} } //Winform窗体的Load事件。 public void Form1_Load(object sender,EventArgs e){ List<Area> areas=new List<Area>(){ new Area(){Id=1,Name="北京",PId=0}, new Area(){Id=2,Name="海淀区",PId=1}, new Area(){Id=3,Name="朝阳区",PId=1}, new Area(){Id=4,Name="东城区",PId=1} }; TreeMap<Area,TreeNode> treeMap=new TreeMap<Area,TreeNode>(); treeMap.Each( () ); //将数据从List<Node>_src加载到TreeView中。这里你不再需要写复杂的遍历算法 Area srcRoot = new Area() { Name = "china", Id = 0 }; TreeMap<Area> areaToTreeNode = new TreeMap<Area>(areas, srcRoot); areaToTreeNode.Each<TreeNode>( //筛选条件用于筛选根节点,需要的是,要自己指定一个返回false的值,用于退出递归,否则将会出现死递归。 (eachElementWithinSrc, specifiedRoot) => { //递归条件。 if(eachElementWithinSrc.Id == specifiedRoot.Id) return false; return eachElementWithinSrc.PId == specifiedRoot.Id; }, //将Area映射到TreeNode (srcElement, root) => { //首先判断,如果根节点等于null,就创建一个根节点。 if(root == null) { root = treeView1.Nodes.Add("china"); return root; } //创建一个新节点 TreeNode newNodeAsRoot = new TreeNode(srcElement.Name); newNodeAsRoot.Tag = srcElement; //将新节点添加到root下,使其成为root的子节点。 root.Nodes.Add(newNodeAsRoot); //返回新创建的节点。 return newNodeAsRoot; } ); }
View Code
相关文章推荐
- 使用 Android Compatibility Package 来简化开发工作
- Python web框架Django学习(1)——在win7 64bit下配置开发环境Django:一个可以使Web开发工作愉快并且高效的Web开发框架。 使用Django,使你能够以最小的代价构建和
- 从零开始搭建一个完善的MVP开发框架(四) —对View(Activity,Fragment等)层组件进行封装简化View层的开发
- 【iOS7开发笔记】tableview之使用xib封装一个view的步骤
- 集合框架(三)使用Iterator接口来遍历一个集合和使用for-each循环简化
- 使用Node.js开发一个在线聊天应用——准备工作
- EasyJWeb作为一个快速Java Web MVC框架,其设计目标不尽是要简化软件开发人员的代码书写工作,更是要能方便界面设计人员的工作。
- 开源一个我的Java工具类集合,帮你简化开发工作
- 在iOS开发中使用反射减少一些代码工作
- Linux多线程开发(二):使用C++封装线程同步操作
- 使用git submodule管理一个需要多个分立开发或者第三方repo的项目
- 一个封装好的SqlHelper类库,可以直接使用
- Kotlin:使用Kotlin开发一个命令行计算器
- 一个DBA对于开发人员使用MySQL的tips
- 使用xib封装一个自定义View
- Linux下Socket的简单使用及最简化封装
- 使用jQuery、Yahoo API和HTML5的geolocation来开发一个天气预报web应用
- 开发一个适合Ajax+JSON+jQuery环境使用的多功能页码栏——jPagerBar-1.1.1
- 使用 Spring Data JPA 简化 JPA 开发
- 快速了解微信小程序的使用,一个根据小程序的框架开发的todos app