树的中序遍历一个非递归实现的一些理解

来源:互联网 发布:淘宝店铺粉丝机器 编辑:程序博客网 时间:2024/06/14 16:36

 Status InOrderTraverse1(BiTree T,Status(*Visit)(TElemType))
 { // 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。

   // 中序遍历二叉树T的非递归算法(利用栈),对每个数据元素调用函数Visit
   SqStack S;
   InitStack(S);
   while(T||!StackEmpty(S))
   {
     if(T)
     { // 根指针进栈,遍历左子树
       Push(S,T);
       T=T->lchild;
     }
     else
     { // 根指针退栈,访问根结点,遍历右子树
       Pop(S,T);
       if(!Visit(T->data))
         return ERROR;
       T=T->rchild;
     }
   }
   printf("/n");
   return OK;
 }

 

说明:这里的BiTree链式存储树的一个数据结构

         这里的SqStack(及相关函数)是用顺序存储结构实现的非循环栈

理解:

      1:这里的结点访问操作:Visit(T->data)由结点的指向孩子的空指针驱动,

      而且每个控制针会驱动一个树的结点被访问

      2:谈到第一点,我们要解决的问题是每个结点都要有相应的空指针做驱动;

      这样的话,在数学上,空指针的个数不能少于结点个数,实际上,有二叉树树的特性可知:

      设树的结点树为n,则分支数(指针数)为2n,而指向结点的分支数为n-1,(没有指向根结点的分支)

      则空分支数(空指针)为2n-(n-1) = n+1,显然n+1大于n

      3:逻辑控制,我们来看这段代码:

      if(T)
     { // 根指针进栈,遍历左子树
       Push(S,T);
       T=T->lchild;
     }
     else
     { // 根指针退栈,访问根结点,遍历右子树
       Pop(S,T);
       if(!Visit(T->data))
         return ERROR;
       T=T->rchild;
     }
    

     左边的叶子节点最先被访问,每个结点被访问后,它的右孩子才会入栈。

     4:最小原型分析:

          1: 只有根节点,则驱动访问根结点的是它的左指针

          2: 有根节点,有左孩子,没有右孩子,则驱动做孩子被访问的是左孩子的左指针,

          而根结点的访问由做孩子的右指针驱动

          3: 有根节点,有右孩子,没有左孩子,则驱动根结点的是根节点的左指针,而启动有孩子的是右孩子的左指针

          4: 既有左孩子,又有右孩子,则驱动左孩子与根节点的规律与2同,驱动右孩子的规律与3同

     5: 递归定义的利用,我们可以有以上的四个最小原型推而广之,利用递归的规律,加上空指针与结点的数学关系

      可以判定该算法的有效性。

原创粉丝点击