我在数据库中查询结构中的记录如下
ID |期限| PARENTID
在C#代码中,我有以下课程
public class Tree
{
public string Id { get; set; }
public string Term { get; set; }
public string ParentId { get; set; }
public int Level { get; set; }
public IList<Tree> ChildItems { get; set; }
}
查询返回5 000 000条记录。
我需要构建Tree项树的树并填充它。
首先,我选择ParentID
为空的所有项目,然后为每个元素搜索父项(如果父项不存在,我构建父项的父项,依此类推),并使用递归构建树。
我对我的算法不满意,因为它需要超过5分钟。
请给我一些建议,如何使用,等等。
这就是现在实现代码的方式:
private string Handle2(List<Tree> originalTree)
{
IList<Tree> newTree = new List<TreeTest.Models.Tree>();
IList<Tree> treeWithoutParents = originalTree.Where(x => String.IsNullOrEmpty(x.ParentID)).OrderBy(x => x.Term).ToList();
foreach(Tree item in treeWithoutParents)
{
Tree newItem = new Tree { Id = item.ID, Term = item.Term, ParentId = item.ParentID, Level = 0 };
newTree.Add(newItem);
InsertChilds(newItem, originalTree, 0);
}
return "output";
}
private void InsertChilds(Tree item, List<Tree> origTree, int level)
{
++level;
IList<Tree> childItems = origTree.Where(x => x.ParentID == item.Id).ToList();
origTree.RemoveAll(x => x.ParentID == item.Id);
foreach (Tree i in childItems)
{
origTree.Remove(i);
}
foreach (Tree tItem in childItems)
{
if (item.ChildTree == null)
{
item.ChildTree = new List<TreeTest.Models.Tree>();
}
Tree itemToAdd = new Tree { Id = tItem.ID, Term = tItem.Term, ParentId = tItem.ParentID, Level = level };
this.InsertChilds(itemToAdd, origTree, level);
item.ChildTree.Add(itemToAdd);
}
}
答案 0 :(得分:0)
尝试使用ID(string
的地图(C#Dictionary),尽管我很奇怪为什么这不是int
}到节点({{1}对象)存储树节点。
这将允许您获得与具有预期O(1)复杂度的ID相对应的节点,而不是您当前的O(n)复杂度。
除此之外,我建议你重新思考一下你的方法 - 尝试编写代码,只涉及一次输入数据,只使用一个字典 - 如果父母还没有,你可以为父级创建一个填充项目,只有当你到达该项目时才会填充其成员。
答案 1 :(得分:0)
我会使用字典(哈希表)来加快速度。这是我在伪代码中的算法:
- create a dictionary mapping ID to IList<Tree> // mapping a node to its children
- create Queue<string,string> of IDs //item (3,5) in the queue corresponds to a node with ID=3 that has a parent with ID=5
- initialize the queue with all the codes with no parent
- List<Tree> withoutParent = dictionary[null]
- for each item in withoutParent:
- add (item.Id, null) to the queue
- while queue is not empty:
- (id,pid) = delete an item from the queue
- make a new node t
- t.Id = id
- t.parentId = pid
- t.ChildItems = dictionary[id]
- for each child in t.ChildItems:
- add (child.Id, id) to the queue
答案 2 :(得分:0)
是列ID唯一标识符。如果是,那么您可以尝试以下方法。不使用List,而是使用Set或hashmap。这是因为如果父项有太多子项,则在列表中查找会降低您的操作速度。如果使用Set,则可以快速查找,也可以快速添加元素。
此外,您可以查看order by子句需要多长时间。这可能真的可以帮助您加快您的流程。如果ID是聚集索引,您将获得快速排序(因为数据已经排序),否则您的查询仍将使用相同的索引
如果父项不存在,则表示您正在创建父项的父项。我会尽量避免这种情况。您可以做的是,如果树中不存在子项的父项,请将其添加到单独的列表中。完成原始列表后,再进行第二次传递以查找孤立元素。优点是,每次创建父级父级时都不需要调整树的大小,然后发现父级位于列表的末尾