轉自: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(); }