如何遍历具有多个级别的树以查找当前元素的上一个和下一个元素?

时间:2011-11-07 21:31:02

标签: c# entity-framework

如何在具有子列表的树中找到任何给定元素的上一个和下一个元素?

实施例


  1. 1.1 AA
    1.1.1 AAA
    1.1.2 BBB
    1.1.3 CCC
  2. 1.2 DD

    我如何获得1.1.3 CCC的上一个和下一个id?我只知道特定时刻的CCC ID。

    我正在使用的真实示例是一个Category实体,它与自身具有递归关联,因为它可以包含SubCategories。如果我在3级子类别中,我想知道上一个和下一个类别的ID。

    在我的视图(网页)中,我有一个所有类别的列表。当我点击一个类别时,我只知道它自己的id,但是想获得上一个和下一个id。

    我使用了以下方法,但是当有更多级别时它们不起作用:

    private void GetNextCategoryID(PagedData<ShowQuestionViewModel> questionsPaged)
        {
    
            List<Category> categories = db.Category.Where(y => y.parrent_id == null).ToList();
    
            categories.Sort(new CompareCategory());
    
            List<ShowCategoriesViewModel> scvm = Mapper.Map<List<Category>, List<ShowCategoriesViewModel>>(categories);
    
            for (int i = 0; i < scvm.Count; i++)
            {
                if (scvm[i].category_id == questionsPaged.CategoryID)
                {
                    if (scvm[i].SubCategories != null && scvm[i].SubCategories.Count > 0)
                    {                          
                            questionsPaged.NextCategory_ID = scvm[i].SubCategories.First().category_id;
                            break;                   
                    }
    
                    try
                    {
                        questionsPaged.NextCategory_ID = scvm[i + 1].category_id;
                        break;
                    }
                    catch (ArgumentOutOfRangeException ex)
                    {
                        questionsPaged.NextCategory_ID = 0;
                        break;
                    }
    
                }
                else if (scvm[i].SubCategories != null)
                {
                    for (int q = 0; q < scvm[i].SubCategories.Count; q++)
                    {
                        if (scvm[i].SubCategories[q].category_id == questionsPaged.CategoryID)
                        {
                            try
                            {
                                questionsPaged.NextCategory_ID = scvm[i].SubCategories[q + 1].category_id;
                                break;
                            }
                            catch (ArgumentOutOfRangeException ex)
                            {
                                // Betyder at vi er kommet til den sidste kategori i rækken
                                // og at den endnu ikke har fundet en match
    
                                try
                                {
                                    questionsPaged.NextCategory_ID = scvm[i + 1].category_id;
                                    break;
    
                                }
                                catch (ArgumentOutOfRangeException eq)
                                {
                                    // Dette betyder at den valgte underkategori kategori er den sidste i spørgeskemaet
                                    questionsPaged.NextCategory_ID = 0;
                                    break;
                                }
    
                            }
                        }
                    }
                }
    
            }
        }
    

    private void GetPreviousCategoryID(PagedData<ShowQuestionViewModel> questionsPaged)
        {
            List<Category> categories = db.Category.Where(y => y.parrent_id == null).ToList();
            categories.Sort(new CompareCategory());
            List<ShowCategoriesViewModel> scvm = Mapper.Map<List<Category>, List<ShowCategoriesViewModel>>(categories);
    
            for (int i = scvm.Count - 1; i >= 0; i--)
            {
                if (scvm[i].category_id == questionsPaged.CategoryID)
                {
                    try
                    {
                        if (scvm[i - 1].SubCategories != null)
                        {
                            int subcount = scvm[i - 1].SubCategories.Count;
                            questionsPaged.PreviousCategory_ID = scvm[i - 1].SubCategories[subcount - 1].category_id;
                            break;
                        }
                        else
                        {
                            questionsPaged.PreviousCategory_ID = scvm[i - 1].category_id;
                        }
    
                    }
                    catch (ArgumentOutOfRangeException ex)
                    {
                        questionsPaged.CategoryID = scvm[i].category_id;
                        break;
                    }
                }
    
                else if (scvm[i].SubCategories != null)
                {
                    for (int x = 0; x < scvm[i].SubCategories.Count; x++)
                    {
                        try
                        {
                            if (scvm[i].SubCategories[x].category_id == questionsPaged.CategoryID)
                            {
    
                                questionsPaged.PreviousCategory_ID = scvm[i].SubCategories[x - 1].category_id;
                                break;
                            }
                        }
                        catch (ArgumentOutOfRangeException qx)
                        {
                            questionsPaged.PreviousCategory_ID = scvm[i].category_id;
                        }
                    }
                }
            }
        }
    

    谢谢!

2 个答案:

答案 0 :(得分:0)

理论上,你应该做的是:使用当前类别的id,遍历树,直到找到具有该id的节点。一旦到了这里,找到继任者(我假设继任者在右边)你必须回到树上:如果父母有一个正确的孩子,找到以该孩子为根的子树的最左边的节点,否则,申请这种推理递归到父母的父母等等。

要查找前一个,只需执行上述步骤,但检查父项是否有左子项并找到该子树的最右侧节点,或递归应用于父项的父项。

// finds the successor of node
procedure successor(node) 
{
    // assuming you have the node for the id that you know.
    // also I'm assuming you have some way to find its position 
    // in the child list

    // if the parent has a child to the right
    if(parent(node).children[position(node) + 1] != null)
    {
        return findLeftmost(parent(node).children[position(node) + 1]);
        // find the leftmost node in the subtree rooted 
        // at the next sibling to the  right
    }
    else
    {
        return successor(parent(node));
        // move up the tree
    }
}


// finds the leftmost leaf node of the (sub)tree rooted at node
procedure findLeftmost(node)
{
    if(node.children.length == 0) // leaf node
    {
        return node;
    }
    else
    {
        return findLeftmost(node.children[0]); 
        // here I'm assuming the children are in the list from left to right, 
        // such that children[0] is the leftmost child.
    }
}

答案 1 :(得分:0)

如果是这样的话,我不太清楚我理解你的问题,所以请提前道歉。

在我看来,您在节点列表中有索引,并且您知道它的级别,因此您只需要跳过视图中具有更高级别的前一个或下一个节点(即它们是子级节点)直到你找到一个具有相同(因此兄弟)级别或更低级别的节点,或者你的节点用完了,在这种情况下,该级别没有兄弟节点。