先序、中序、后序遍历的递归类似:

递归算法:

1 void PreOrder(BiTree *T)//先序遍历 
2  {
3      if(T!=NULL)
4      {
5          printf("%c",T->data);
6          PreOrder(T->lchild);
7          PreOrder(T->rchild);
8      }
9  }

非递归算法:先序遍历是访问顺序为根左右。首先初始化一个栈,初始化栈,让二叉树一直从根结点开始一直访问左子树直到为NULL,同时也输出访问结点的数值,在

把该结点入栈,当左子树为NULL时,就指向栈顶结点的右孩子结点,栈顶出栈,如果右孩子结点为NULL则继续出栈,不为空,就继续进行之前的操作。

  1. 依次访问左子树且输出左子树的data域并入栈,直到左子树为NULL
  2. 左子树为NULL时,令取栈顶元素的右孩子,出栈并访问右子树。
    1. 若右子树为NULL则继续取栈顶元素的右孩子并出栈,
    2. 不为NULL时,则重新操作1。
  3. 结束操作为:当栈为空且访问的结点为NULL时。

   

 void PreOrder1(BiTree *T)//先序遍历的非递归算法 
 {
     BiTree *st[MaxSize];
     int top=-1;
     while(T!=NULL||top!=-1)
     {
         if(T!=NULL)
         {
             Visit(T);
             st[++top]=T;
             T=T->lchild;
         }
         else
         {
             T=st[top--];
             T=T->rchild;
         }
     }
  } 

中序遍历的非递归与先序类书:

后序遍历的非递归算法:后序遍历的访问顺序为左右根。关键在于要有关键值来判断该结点的左右子树是否访问过了,只有当访问过后才能输出该结点。所以可以在栈中设置一个flag域作为关键值。

  1. 当左子树不为NULL时,依次访问左子树且入栈,且令该结点在栈中的flag域表示为访问过左孩子了。
  2. 左子树为NULL时,取栈顶结点,当该结点的右孩子为NULL时,将该结点出栈并输出该结点的值,继续取栈顶结点。若该结点的右孩子不为NULL,则将该结点在栈中的flag域设置为访问过右孩子了,然后在指向孩子的右结点,重复操作1.
  3. 当栈为NULL时就结束。(这儿不需要指向结点为NULL)
 1 void PostOrder1(BiTree *t)//后序的非递归算法 
 2  {
 3      BStack st[MaxSize];
 4      /*
 5      for(int i=0;i<MaxSize;i++)
 6      {
 7          printf("%d\n",st[i].flag);
 8      }
 9      结构体数组可不会初始化为0 
10      */
11      for(int i=0;i<MaxSize;i++)
12      {
13          st[i].flag=0;//标志位,判断是否访问过左右子树 ,0表示左未访问,2表示右孩子被访问过 
14      }
15      int top=0;
16      do
17      {
18          while(t!=NULL&&st[top].flag==0)//左子树依次入栈,且未被访问过 
19          {
20              st[top].data=t;
21              st[top].flag=1;
22              t=t->lchild;
23              top++;
24          }
25          if(st[top].flag==0)//这个就是如果已经是栈里面的就不需要在取栈的元素了 
26          {
27          top--;
28          t=st[top].data;
29         }    
30          if(t->rchild!=NULL&&st[top].flag!=2)//右子树不为空且未被访问过。 
31          {
32              t=t->rchild;
33              st[top++].flag=2;//标记该节点的右子树被访问过。 
34          }
35          else
36          {
37              printf("%c",t->data);
38              st[top].flag=0;
39             /*
40             因为这个是我逻辑上定义的栈,所以出栈操作只是把top指针改变了,没有改变里面的值,所以要手动的把
41             flag值归为初始值。如果自己定义的链栈的话,出栈就是纯粹的出栈了。 我自己的出栈就不纯粹。 
42             */ 
43              top--;
44              t=st[top].data;
45          }
46      }while(top!=-1);
47  }

 上面是自己写的。

下面附上教材上的代码: