转自:https://www.jb51.net/article/125747.htm前端
树形结构:最近在作任务管理,任务能够无限派生子任务且没有数量限制,前端采用Easyui的Treegrid树形展现控件。node
a.JSON数据格式:ui
[ { "children":[ { "children":[ ], "username":"username2", "password":"password2", "id":"2", "pId":"1", "name":"节点2" }, { "children":[ ], "username":"username2", "password":"password2", "id":"A2", "pId":"1", "name":"节点2" } ], "username":"username1", "password":"password1", "id":"1", "pId":"0", "name":"节点1" } ]
b.定义实体必要字段this
为了Tree结构的通用性,咱们能够定义一个抽象的公用实体TreeObject以保证后续涉及到的List<T>转化树形JSONspa
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyTree.Abs { public class TreeObejct { public string id { set; get; } public string pId { set; get; } public string name { set; get; } public IList<TreeObejct> children = new List<TreeObejct>(); public virtual void Addchildren(TreeObejct node) { this.children.Add(node); } } }
c.实际所需实体TreeModel让它继承TreeObject,这样对于id,pId,name,children咱们就能够适用于其它实体了,这也至关于咱们代码的特殊约定:.net
using MyTree.Abs; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace MyTree.Models { public class TreeModel : TreeObejct { public string username { set; get; } public string password { set; get; } } }
二、递归遍历pwa
获取所有任务并转化为树形线程
获取所有任务转化为树形是比较简单的,咱们首先获取到pId=0的顶级数据(即不存在父级的任务),咱们经过顶级任务依次递归遍历它们的子节点。htm
/ //递归获取全部树结构的数据 public IList<TreeObject> GetData() { List<TreeObject> nodes = _context.Node.Where(x => x.parent_node_id == 0).Select(x=>new TreeObject { id=x.id,pId=x.parent_node_id,name=x.name}).ToList(); foreach(TreeObject item in nodes) { item.children = GetChildrens(item); } return nodes; } //递归获取子节点 public IList<TreeObject> GetChildrens(TreeObject node) { IList<TreeObject> childrens = _context.Node.Where(c => c.parent_node_id == node.id).Select(x => new TreeObject { id = x.id, pId = x.parent_node_id, name = x.name }).ToList(); foreach (TreeObject item in childrens) { item.children = GetChildrens(item); } return childrens; }
三、非递归遍历blog
非递归遍历在操做中不须要递归方法的参与便可实现Tree的拼接
对于以上的代码,咱们不须要修改,只须要定义一个非递归遍历方法NotRecursion:
public static void NotRecursion() { #region 非递归遍历 System.Diagnostics.Stopwatch sw2 = new System.Diagnostics.Stopwatch(); sw2.Start(); Dictionary<string, TreeObejct> dtoMap = new Dictionary<string, TreeObejct>(); foreach (var item in models) { dtoMap.Add(item.id, item); } IList<TreeObejct> result = new List<TreeObejct>(); foreach (var item in dtoMap.Values) { if (item.pId == "0") { result.Add(item); } else { if (dtoMap.ContainsKey(item.pId)) { dtoMap[item.pId].AddChilrden(item); } } } sw2.Stop(); Console.WriteLine("----------非递归遍历用时:" + sw2.ElapsedMilliseconds + "----------线程名称:" + t2.Name + ",线程ID:" + t2.ManagedThreadId); #endregion
main.cs
private static IList<TreeObejct> models; private static IList<TreeObejct> models2; private static Thread t1; private static Thread t2; static void Main(string[] args) { int count = 6; Console.WriteLine("生成任务数:"+count+"个"); models = GetData(count); models2 = GetData(count); t1 = new Thread(Recursion); t2 = new Thread(NotRecursion); t1.Name = "递归遍历"; t2.Name = "非递归遍历"; t1.Start(); t2.Start(); Console.Read(); }