1. Loosely based on the Flyout Category Tree mod, use one single sql to query categories, hence reduce the load on server (especially those with large number of categories)
2. Allow users to specify the parent, child tag instead of having to use ul, li
3. Allow the use of session to further reduce the load on server
4. Can build any branch of the category tree.
5. A number of users wanted to list all products in all sub-categories of a specific category, they can take advantage of this mod as well, since it stores all sub-cats of a specific cat in $tree['cat_id']['sub_cats'] array, however, it currently stores the first sub-level, so you have to write a small function to go thru the tree and gather the deepest cats (assuming you understand what I mean ^^)

I wrote this class for my own use, and have no intention to write a detailed instruction, nor provide a downloadable package, nor provide any support at all. Just think that some of you may need it, so I post the code here:

includes/classes/simple_categories_tree_generator.php
PHP Code:
<?php
/**
 * Simple Category Tree
 * @Version: Beta 1
 * @Authour: yellow1912
 * @license http://www.zen-cart.com/license/2_0.txt GNU Public License V2.0
 */ 

define ('SCT_REBUILD_TREE','false');
class 
simple_categories_generator{
    var 
$category_tree = array();

    function 
simple_categories_generator() {
        if(
SCT_REBUILD_TREE != 'false' || count($this->category_tree) == 0){
            global 
$languages_id$db;
            
$categories_query "select c.categories_id, cd.categories_name, c.parent_id
                          from " 
TABLE_CATEGORIES " c, " TABLE_CATEGORIES_DESCRIPTION " cd
                          where c.categories_id = cd.categories_id
                          and c.categories_status=1
                          and cd.language_id = '" 
. (int)$_SESSION['languages_id'] . "'
                          order by c.parent_id, c.sort_order, cd.categories_name"
;
            
$categories $db->Execute($categories_query);
    
            while (!
$categories->EOF) {
                
$this->category_tree[$categories->fields['categories_id']] = array('name' => $categories->fields['categories_name'],
                
'parent_id' => $categories->fields['parent_id']);
                
$this->category_tree[$categories->fields['categories_id']]['path'][] = $categories->fields['categories_id'];
                
$this->category_tree[$categories->fields['parent_id']]['sub_cats'][] = $categories->fields['categories_id'];
                if(
$categories->fields['parent_id'] > 0){
                    
$this->category_tree[$categories->fields['categories_id']]['path'] = array_merge($this->category_tree[$categories->fields['parent_id']]['path'],$this->category_tree[$categories->fields['categories_id']]['path']);
                }
                
$this->category_tree[$categories->fields['categories_id']]['cPath'] = implode('_',$this->category_tree[$categories->fields['categories_id']]['path']);        
                
$categories->MoveNext();
            }
            
// add sub 'class' for print-out purpose
            
foreach($this->category_tree as $key => $value){
                
$this->category_tree[$key]['sub'] = isset($this->category_tree[$key]['sub_cats']) ? 'has_sub' 'no_sub';            
            }    
        }
    }

    function 
build_category_string($parent_tag 'div'$child_tag 'span'$categories_id 0$include_root false){
        if(!
is_int($categories_id)){
            
$temp explode('_',$categories_id);
            
$categories_id $temp(count($temp)-1);
        }
        
$result '';
        
$level 0;
        
$sub $this->category_tree[$categories_id]['sub'];
        if(isset(
$this->category_tree[$categories_id])){
            if(
$include_root && $categories_id 0){
                
$result .= "<$parent_tag class='level_$level $sub'><$child_tag class='level_$level $sub'>".$this->_build_category_string($categories_id,$parent_tag,$child_tag)."</$child_tag></$parent_tag>";
            }
            else{
                if(isset(
$this->category_tree[$categories_id]['sub_cats'])){
                    
$result .= "<$parent_tag class='level_$level $sub'>";
                    foreach(
$this->category_tree[$categories_id]['sub_cats'] as $key => $value){
                        
$sub $this->category_tree[$value]['sub'];
                        
$result .= "<$child_tag class='level_$level $sub'>".$this->_build_category_string($value,$parent_tag,$child_tag)."</$child_tag>";
                    }
                    
$result .= "</$parent_tag>";
                }
            }

        }
        
$result str_replace(array('<>','</>'), ''$result);
        return 
$result;
    }

    function 
_build_category_string($categories_id 0$parent_tag 'div'$child_tag 'span'$level 0){
        
$result $this->build_category_link($this->category_tree[$categories_id]['name'],$this->category_tree[$categories_id]['cPath']);
        
$level++;
        
$sub $this->category_tree[$categories_id]['sub'];
        if(isset(
$this->category_tree[$categories_id]['sub_cats'])){
            
$result .= "<$parent_tag class='level_$level $sub'>";
            foreach(
$this->category_tree[$categories_id]['sub_cats'] as $key => $value){
                
$sub $this->category_tree[$value]['sub'];
                
$result .= "<$child_tag class='level_$level $sub'>".$this->_build_category_string($value,$parent_tag,$child_tag$level)."</$child_tag>";
            }
            
$result .= "</$parent_tag>";
        }
        return 
$result;
    }

    function 
build_category_link($categories_name$cPath){
        return 
'<a href="' zen_href_link(FILENAME_DEFAULT'cPath=' $cPath) . '">'.$categories_name.'</a>';
    }
}