建树的基本思路:从根节点开始递归调用显示子树

本文介绍了一个基于.NET平台的动态菜单构建方法,通过SQL查询填充数据集,并递归创建树状菜单结构,实现了灵活且可扩展的菜单系统。

数据库如下:

NodeId ParentId NodeName Address  Icon
100000 公共查询部  icon_document.gif
100001 100000  人民币日报查询public/a1.aspxicon_settings.gif
100002 100000 外币日报查询public/a2.aspxicon_settings.gif
100003 0分行科技部tech/a1.aspxicon_document.gif
100004100003人民币日报查询tech/a2.aspxicon_settings.gif
100005100003外币日报查询  
1000060福田支行 icon_document.gif
100007100006月存款进度表a1.aspxicon_settings.gif
100008100006月存款走势图a2.aspxicon_settings.gif
1000090罗湖支行 icon_document.gif
100010100009月存款进度表a1.aspx icon_settings.gif
100011100009月存款走势图a2.aspx icon_settings.gif

public class menu_Left : System.Web.UI.Page
 {
  protected Microsoft.Web.UI.WebControls.TreeView tvMenu;
  SqlConnection Conn;
  SqlDataAdapter myCmd;
  DataSet ds;
  string cmdSelect;

  private void Page_Load(object sender, System.EventArgs e)
  {
   Conn=new SqlConnection(Application["ConnString"].ToString());
   CreateDataSet();
   InitTree(tvMenu.Nodes,"0");
  }
  //建立数据集
  private DataSet CreateDataSet()
  {
   cmdSelect="select * from S_Menu";
   myCmd=new SqlDataAdapter(cmdSelect,Conn);
   ds=new DataSet();
   myCmd.Fill(ds,"tree");
   return ds;
  }
  //建树的基本思路是:从根节点开始递归调用显示子树
         private void InitTree(TreeNodeCollection Nds,string parentId)
  {
   DataView dv=new DataView();
   TreeNode tmpNd;
   string intId;
   dv.Table=ds.Tables["tree"];
   dv.RowFilter="ParentId='" + parentId + "'" ;
   foreach(DataRowView drv in dv)
   {
    tmpNd=new TreeNode();
    tmpNd.ID=drv["NodeId"].ToString();
    tmpNd.Text=drv["NodeName"].ToString();
    tmpNd.ImageUrl="../images/"+drv["Icon"].ToString();
    tmpNd.NavigateUrl="../"+drv["Address"].ToString();
    Nds.Add(tmpNd);
    intId=drv["ParentId"].ToString();
    InitTree(tmpNd.Nodes,tmpNd.ID);
   }
  }

 

步骤: 1、初始化:栈 OPTR 中只有一个元素‘#’,栈 OPND 为空栈; 2、依次读入字符,执行下述操作: 2.1ch=读入的字符; 2.2 若 ch 是‘#’,则算法结束,返回栈 OPND 的栈顶元素; 2.3 若 ch 不是运算符,则将入栈 OPND; 2.4 若 ch 是运算符,则 2.4.1t=栈 OPTR 的栈顶元素; 2.4.2 比较 ch 和 t 的优先级,执行下述三种操作之一: (1)若 ch=t:将栈 OPTR 的栈顶元素出栈; (2)若 ch>t:将 ch 插入栈 OPTR 中; (3)若 ch<t:在栈 OPND 中弹出两个元素,与 ch 进行运算, 将结果插入栈 OPND 中; 以以上所描述的步骤为模板,简化重写以下的步骤 第一步:定义数据结构(BiTree.h) 防止头文件重复包含 使用 #ifndef BiTree_H、#define BiTree_H 和 #endif 宏保护,确保头文件只被编译一次。 定义二叉树结点结构体 BiNode 包含一个字符型数据域 data 两个指针:lchild 指向左孩子,rchild 指向右孩子 定义二叉树类 BiTree 公共接口(public): 构造函数:用于创建二叉树 析构函数:自动释放内存 四种遍历函数(前/中/后/层序) 打印单孩结点函数 获取高度函数 私有成员: 根指针 root 多个私有递归辅助函数,对应各操作的底层实现 第二步:构造二叉树(构造函数 + Creat 函数) 调用构造函数 BiTree() 初始化根指针 root = NULL 提示用户:“开始构建二叉树(# 表示空节点):” 递归创建二叉树(Creat(BiNode* bt)) 从标准输入读取一个字符 ch 如果 ch == ‘#’,表示当前子树为空,返回 NULL 否则: 动态分配新节点 bt 将 ch 存入 bt->data 递归创建左子树:bt->lchild = Creat(bt->lchild) 递归创建右子树:bt->rchild = Creat(bt->rchild) 返回该节点指针 此过程采用 前序扩展序列建树法,即按“根→左→右”顺序输入,# 表示空节点 示例输入:A B D # # E # # C F # # G # # 对应的树形结构为: 第三步:实现四种遍历方式 前序遍历(PreOrder) 访问顺序:根 → 左子树 → 右子树 实现方式:递归访问当前节点,先输出数据,再递归处理左右子树 中序遍历(InOrder) 访问顺序:左子树 → 根 → 右子树 常用于输出排序结果(若为二叉搜索树) 后序遍历(PostOrder) 访问顺序:左子树 → 右子树 → 根 常用于释放内存或求表达式树值 层序遍历(LevelOrder) 使用 STL 中的 queue<BiNode*> 实现广度优先搜索(BFS) 步骤如下: 若根为空,直接返回 将根节点入队 循环直到队列为空: 取出队首节点并输出其数据 若有左孩子,则将其入队 若有右孩子,则将其入队 实现了从上到下、从左到右逐层访问 第四步:输出仅有一个孩子的结点(PrintSingleChild) 使用递归方式,在前序遍历过程中判断每个结点的孩子情况: 条件:(左空且右非空) 或 (左非空且右空) 满足条件时输出该结点的数据 遍历顺序仍为前序(先访问根,再左右子树) 例如在上述例子中,如果某个结点只有左孩子或只有右孩子,则会被打印出来 第五步:计算二叉树的高度(GetHeight) 高度定义:从根到最远叶子的最长路径上的边数(或层数减一),通常以 最大深度 表示 实现方法:递归 空树高度为 0 非空树高度 = max(左子树高度, 右子树高度) + 1 使用 中的 std::max 函数比较左右子树高度 第六步:释放内存(析构函数 + Release 函数) 调用析构函数 ~BiTree() 自动调用 Release(root) 释放整棵树 Release(BiNode* bt) 函数逻辑 采用后序遍历策略释放内存: 先递归释放左子树递归释放右子树 最后释放当前节点 这样可以保证在删除父节点前,所有子节点已被释放,避免悬空指针 第七步:主函数控制流程(main.cpp) 创建 BiTree T 对象 自动触发构造函数,开始交互式建树 依次调用以下功能并输出结果: T.PreOrder():输出前序遍历序列 T.InOrder():输出中序遍历序列 T.PostOrder():输出后序遍历序列 T.LevelOrder():输出层序遍历序列 T.PrintSingleChild():输出只有一个孩子的结点 T.GetHeight():输出整棵树的高度 程序结束前自动调用析构函数,清理内存
最新发布
10-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值