如何在具有子列表的树中找到任何给定元素的上一个和下一个元素?
实施例
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;
}
}
}
}
}
谢谢!
答案 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)
如果是这样的话,我不太清楚我理解你的问题,所以请提前道歉。
在我看来,您在节点列表中有索引,并且您知道它的级别,因此您只需要跳过视图中具有更高级别的前一个或下一个节点(即它们是子级节点)直到你找到一个具有相同(因此兄弟)级别或更低级别的节点,或者你的节点用完了,在这种情况下,该级别没有兄弟节点。