The "Best Way" would be with a custom page template.  Just like index.php loops through all the posts, you can run a custom query to loop through everything and only echo the information you want (title, URL) to the browser.

Here are some good tutorials for building a custom page template:


WordPress Codex
WordPress Max (w/ video tutorial)


Create an "All Posts" or "Archives" Page with WordPress 3.0?
My CTE runs in an infinite loop for a specific customer and I am not able to find out why.

Here is the query:

;WITH ClassTree
           AS (SELECT ID, NAME, Parent_ID
               FROM   TableName
               WHERE  ID = 1
               UNION ALL
               SELECT T.ID, T.NAME, T.Parent_ID
               FROM   TableName T WITH (NOLOCK)
                      JOIN ClassTree
                        ON Parent_ID = ClassTree.ID
)
SELECT * FROM ClassTree

