標籤:get mod 非遞迴遍曆 children lis private stop virt stat
轉自:https://www.jb51.net/article/125747.htm
樹形結構:最近在做任務管理,任務可以無限派生子任務且沒有數量限制,前端採用Easyui的Treegrid樹形展示控制項。
a.JSON資料格式:
[ { "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.定義實體必要欄位
為了Tree結構的通用性,我們可以定義一個抽象的公用實體TreeObject以保證後續涉及到的List<T>轉化樹形JSON
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我們就可以適用於其它實體了,這也相當於我們代碼的特殊約定:
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; } }}
2、遞迴遍曆
擷取全部任務並轉化為樹形
擷取全部任務轉化為樹形是比較簡單的,我們首先擷取到pId=0的頂級資料(即不存在父級的任務),我們通過頂級任務依次遞迴遍曆它們的子節點。
/ //遞迴擷取所有樹結構的資料 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; }
3、非遞迴遍曆
非遞迴遍曆在操作中不需要遞迴方法的參與即可實現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();}
C#構建樹形資料結構