Recursion algorithm for creating a sitemap

I have a DataTable containing a sitemap hierarchy with the following columns:

  • ItemId
  • ParentId
  • Name
  • Url

I need to generate a set of nested lists in HTML (anchor elements left for clarity):

<ul>
<li>Item 1</li>
<li>Item 2</li>
    <ul>
    <li>Sub Item 1</li>
    <li class="current">Sub Item 2</li>
    </ul>
<li>Item 3</li>
</ul>

      

The tree should only contain branches that lead to the "current" node / page (so using the above example, any child items that Item '1' or '3' are not displayed. Can anyone help with some example pseudocode / code that can traverse the tree from leaf to root, generating HTML, how does it go? Thanks.

0


source to share


4 answers


Here's some pseudocode. The idea is simple: start at all untagged nodes and mark the node's current parent, its parent, etc., until you get to the root. By doing this, you will accurately mark the nodes along the path from the current node to the root. Then you can just print all the nodes in another pass, recursive only on the "marked" nodes. This is optimal (runtime is the maximum number of nodes you should print).

for all n: mark[n]=False
n=current
while n!=root:
    n=parent[n]
    mark[n]=True

def print_tree(n):
    print_node(n)
    if mark[v]==True:
        print '<ul>'
        for each child c of n: print_tree(c)
        print '</ul>'

def print_node(n):
   if n==current: print '<li class="current">' else: print '<li>'
   print name[n]
   print "</li>"

print_tree(root)

      



parent[n]

and name[n]

probably something like n.parent

that n.name

in your structure too. About the "per child n" part - I am assuming that you have an adjacency list containing a list of all children of a given node. (If you don't, what is the order in which the children should be printed?) Either way, adjacency lists can be built in O (number of nodes) time by simply adding each node to the children, the list of its parent. The total size of the lists does not exceed the number of nodes (since each node other than the root occurs in only one of the lists), so these lists do not take up much memory (one list can contain many elements, but the total size is limited).

+2


source


A more efficient way to do this, if you can change the data structure, is to use nested sets:

Managing hierarchical data in MySQL



Using the Nested Set Data Model for Breadcrumb References

+2


source


I did something similar, it might not be that efficient, but it's easy to debug.

  • Find the path to the selected node.
  • Add rootnodes to the list.
  • Find a node in the list that is in the path.
  • Add all childern to this node.
  • Find the next node in the path.
  • Repeat 4-5 until at the selected node, and if not, add the selected childern nodes as well.

Alternative: 1. Find the selected node, print this and all siblings 2. Print the parent and all siblings around line from 1. 3. Repeat 2 up to the root.

0


source


This is VBScript, and while I haven't tried to run it, so it may contain bugs, it should give you the basic idea.

'# OMITTED: Code to retrieve the record for the current node, and read all info about it.
'# Note: field values are read into variables with the same names.

Dim RootFound
Dim ListHTML
RootFound = false
ListHTML = ""

if ParentID = Null then RootFound = true
ListHTML = "<ul><li>" & Name & "</li></ul>"

while not RootFound
  SQL = "SELECT * FROM DataTable WHERE ItemID = " & ParentID
  '# OMITTED: Code to open dataset using the SQL statement above and 
  'fetch all field values into identically named variables

  ListHTML = "<ul><li>" & Name & "</li>" & ListHTML & "</ul>"
  if ParentID = Null then RootFound = true
wend

      

0


source