【问题标题】:C# Large Tree IterationC# 大树迭代
【发布时间】:2009-02-03 18:18:44
【问题描述】:

我有一个以父/子关系组装的大型结果集。我需要遍历树并向用户显示结果。

我在使用递归之前已经这样做了,但是因为我的结果集可能很大,所以我想避免收到 StackOverflowException 的可能性。

我在使用堆栈的 MSDN 上找到了以下 example。我遇到的问题是因为堆栈是后进先出的,我的数据显示不正确。我希望它看起来像下面这样:


LeveL 1
Level 1.1
Level 1.1.1 
Level 1.1.2 
Level 1.2 
Level 1.2.1 
Level 1.2.2

但它看起来像:


LeveL 1
Level 1.2 
Level 1.2.2 
Level 1.2.1 
Level 1.1 
Level 1.1.2 
Level 1.1.1 

有什么想法吗?

这是我的代码示例。假设DataTable dt 具有以下列:ID、ParentID 和 Text

    private struct Item
    {
        public string Text;
        public int ID;
        public int ParentID;
    }

    private void BuildView()
    {
        Stack<Item> itemTree = new Stack<Item>(40);

        //Get All Parent Nodes
        DataView dv = new DataView(dt);
        dv.RowFilter = "ParentID = 0";

        //Add the parent nodes to the stack
        foreach (DataRowView drv in dv)
        {
            Item item = new Item();
            item.Text = drv["Text"].ToString();
            item.ID = drv["ID"].ToString();
            item.ParentID = drv["ParentID"].ToString();
            itemTree.Push(item);
        }

        //Go through the stack one node at a time
        while (itemTree.Count > 0)
        {
            Item currentItem = itemTree.Pop();
            Debug.WriteLine(currentItem.Text);

            //Get children of current node
            dv.RowFilter = String.Format("ParentID = {0}", currentItem.ID);
            if (dv.Count > 0)
            {
                //Add child nodes to the stack
                foreach (DataRowView drvChild in dv)
                {
                    Item item = new Item();
                    item.Text = drvChild["Text"].ToString();
                    item.ID = drvChild["ID"].ToString();
                    item.ParentID = drvChild["ParentID"].ToString();
                    itemTree.Push(item);
                }
            }
        }

    }

【问题讨论】:

    标签: c# algorithm recursion iteration tree-traversal


    【解决方案1】:

    在当前算法中,您首先要寻找正确的孩子。

    首先让它成为左孩子。就是这样。

    例如,在您的代码中可能有如下内容:

    node = node.rightChild()
    

    改成

    node = node.leftChild()
    

    这是此类问题的一般解决方案。

    由于 MSDN 实现没有公开这种代码,我无法对此发表评论。

    【讨论】:

    • 我认为那里有一个错字...两行代码是相同的。
    【解决方案2】:

    以相反的顺序将您的项目推入堆栈,即 2 在 1 之前。

    例子:

    // suppose I want to push children[] onto the stack
    
    for (int i = children.Length - 1; i >= 0; i--)
    {
       stack.Push(children[i]);
    }
    

    要在您的代码中执行此操作,请尝试以下 for-each 语句:

    foreach (DataRowView drvChild in dv.Reverse())
    

    【讨论】:

    • @Niyaz:用一个例子更新了我的答案。
    • 是的。但是你能解释一下这将如何给出所需的答案吗?我无法理解。
    • @Niyaz:我认为这适用于 OP 使用堆栈的特定方式。猜猜这取决于您如何使用堆栈进行遍历。
    • 有更好的方法吗?
    • @djdouma:我认为你的方式最适合所需的输出。
    【解决方案3】:

    如果只是提供关注的顺序,请从使用堆栈更改为使用队列。它们在实际用途上是相同的,不同之处在于队列是先进先出的。

    【讨论】:

    • 使用队列将其更改为广度优先遍历,而不是所需的深度优先遍历。
    • 扎克,不一定。只有先做广度,它才会成为广度优先。但通常我们在广度优先搜索中使用队列。
    • 如果我使用队列,数据看起来像这样。 1 级 1.1 级 1.2 级 1.1.1 级 1.1.2 级 1.2.1 级 1.2.2 级
    【解决方案4】:

    通过以相反的顺序更改子节点的迭代,它们按需要显示

    //Add child nodes to the stack
    for (int i = dv.Count - 1; i >= 0; i--)
    {
        DataRowView drvChild = dv[i];
        Item item = new Item();
        item.Text = drvChild["Text"].ToString();
        item.ID = drvChild["ID"].ToString();
        item.ParentID = drvChild["ParentID"].ToString();
        itemTree.Push(item);
    }
    

    【讨论】:

    • 错字?索引 i 似乎没有被使用。
    猜你喜欢
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    相关资源
    最近更新 更多