How do i find the previous and next element of any given element in a tree that has sublists?
Example
- A
1.1 AA
1.1.1 AAA
1.1.2 BBB
1.1.3 CCC
1.2 DD
How do i get the previous and next id’s of 1.1.3 CCC ? I only know the ID of CCC at the given moment.
The real example i am working with is a Category entity which has a recursive association to itself because it can contain SubCategories. If i am in a level 3 subcategory, i would like to know the ID of the previous and next Category.
In my View (webpage) i have a list of all the categories. When i click on a Category, i only know it’s own id, but would like to get the previous and next id aswell.
I’ve used the following methods but they dont work when there a more levels:
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;
}
}
}
}
}
}
}
and
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;
}
}
}
}
}
Thanks!
In theory, what you should do is this: with the id of the current category, traverse the tree until you find the node with that id. Once here, to find the successor (I’m assuming the successor is to the right) you must go back up the tree: if the parent has a right child, find the leftmost node of the subtree rooted at that child, otherwise, apply this reasoning recursively to the parent of the parent and so on.
To find the predecessor, just do the above steps but check if the parent has a left child and find the righmost node of that subtree, or apply recursively to the parent of the parent.