从记录中构建树结构

时间:2014-04-22 06:35:38

标签: algorithm sorting data-structures tree binary-tree

我在数据库中查询结构中的记录如下

  

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);
    }
}

3 个答案:

答案 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)

  1. 是列ID唯一标识符。如果是,那么您可以尝试以下方法。不使用List,而是使用Set或hashmap。这是因为如果父项有太多子项,则在列表中查找会降低您的操作速度。如果使用Set,则可以快速查找,也可以快速添加元素。

  2. 此外,您可以查看order by子句需要多长时间。这可能真的可以帮助您加快您的流程。如果ID是聚集索引,您将获得快速排序(因为数据已经排序),否则您的查询仍将使用相同的索引

  3. 如果父项不存在,则表示您正在创建父项的父项。我会尽量避免这种情况。您可以做的是,如果树中不存在子项的父项,请将其添加到单独的列表中。完成原始列表后,再进行第二次传递以查找孤立元素。优点是,每次创建父级父级时都不需要调整树的大小,然后发现父级位于列表的末尾