二叉树非递归遍历方式

#include<stdio.h>
#include<stdlib.h>


//描述单一个体,起别名
typedef   struct   treeNode
{
		char    data;  //数据域用字符表示
		struct   treeNode* LChild;    //左子树指针
		struct   treeNode*RChild;    //右子树指针
}TREE,*LPTREE;   //一般用用LP开头的,表示指针别名


//创建二叉树结点
LRTREE   createNode(char   data)
{
         LRTREE   newNode = (LRTREE)malloc(sizeof(TREE));
         newNode->data = data;
         newNode->LChild = NULL;
         newNode->RChild = NULL;
         return   newNode;
}


//没有规律的树
void   insertNode(LRTREE    parentNode,LRTREE    LChild,  LRTREE   RChild)
{
          parentNode->LChild = LChild;
          parentNode->RChild = RChild;
}


//打印当前节点的元素
void    printCurNodeData(LRTREE   curData)
{
         printf("%c\t", cruData->data);
}


//先序非递归打印,通过栈的方式去做
void   preOderByStack(LRTREE   root)
{
        if(root == NULL)
                 return;
         //准备栈
        struct     treeNode*stack[10];    //存储每次打印节点的位置
        int    stackTop = -1;   //栈顶标记           
        //更多时候我们会创建一个数组栈,和一个数组指针,并不会单独去写一个栈结构
        LRTREE   pMove = root;    //从根结点开始打印
        while(stackTop != -1 || pMove)//栈顶标记还可以退,或者pMove不等于NULL
        {
      			 //根,左,右
      			 //直到找到最左边
      			 while(pMove)
      			 {
      			             //入径,加上 打印走过的节点
      			             printf("%c\t",pMove->data);
      			             //位置入栈
      			             stack[++stackTop] = pMove; //stack也是一个结构体指针,下标从0开始
      			             pMove = pMove->LCHild;  //一直往左边找
      			 }
      			 //无路可走的处理,此时由while循环结束,pMove为NULL
      			 //先判断栈是不是空的
      			 if(stackTop != -1)
      			 {
      			          pMove = stack[stackTop];  //获取栈顶元素
      			          stackTop--;                         //出栈
      			          pMove = pMove->RCHild;    //此时pMove为根部的上一个结点,这样就可以判断是否可以往右走
      			 }
		}//通过stackTop加与不加来返回上一个节点,进行循环
}


//递归法
//先序:根->左->右
void   preOrder(LRTREE    root)
{
       if(root  !=  NULL)
       {
               printCurNodeData(root);  //打印根部节点,到左节点,最后右节点
               preOrder(root->LChild);
               preOrder(root->RChild);
               //同样用了preOrder函数,使根节点,左节点,右节点都打印
       }
}


//中序:左->根->右
void   midOrder(LRTREE    root)
{
       if(root  !=  NULL)
       {
                midOrder(root->LChild);//打印左节点,到根节点,最后右节点
                printCurNodeData(root);
               midOrder(root->RChild);
               //同样用了midOrder函数,使根节点,左节点,右节点都打印
       }
}

//中序遍历,采用非递归的方式,左  根   右
void   midOrderByStack(LRTREE    root)
{
     if(root == NULL)
         return;
     //当无路的时候,出栈,打印当前结点中的元素
     //出栈后,打印当前节点元素,判断当前节点是否存在右边,若存在,则去右边
     struct   treeNode* stack[10];
     int   stackTop = -1;

     LRTREE   pMove = root;
     while(stackTop != -1||pMove)
     {
          //我们需要一个指针移动到最左边,并且把走过的位置入栈
          while(pMove)
          {
              stack[++stackTop] = pMove;
              pMove = pMove->LCHild;
          }
          //出栈
          if(stackTop != -1)
          {
              pMove = stack[stackTop--];
              //在这里是先--,再做赋值,stackTop在上面已经++了,这里返回上一个就--
              printf("%c\t",pMove->data);
              pMove = pMove->RCHild;
          }
     }
}


//后序:左->右->根
void   lastOrder(LRTREE    root)
{
       if(root  !=  NULL)
       {
               lastOrder(root->LChild);//打印左节点,到右节点,最后根节点 
               lastOrder(root->RChild);
               printCurNodeData(root);
               //同样用了lastOrder函数,使根节点,左节点,右节点都打印
       }
}

//后序遍历
void   lastOrderByStack(LRTREE    root)
{
     if(root == NULL)
        return;
     struct   treeNode* stack[10];
     int   stackTop = -1;
     
     struct   treeNode*pMove = root;
     struct   treeNode*pLastVisit = NULL;
     //定义一个访问标记

     //左,右,根
     while(pMove)
     {
         stack[++stackTop] = pMove;
         pMove = pMove->LChild; 
     }   //到达最左边
     //出栈
     while(stackTop != -1)
     {
         pMove = stack[stackTop--];
         //判断当前结点是否被访问
         if(pMove->RChild == NULL||pMove->RChild == pLastVisit)
         {
              //如果被访问了,就可以打印当前结点数据
              printf("%c\t",pMove->data);
              pLastVisit=pMove;  //改变标记的位置
         } 
         else  //右边没访问完
         {
               stack[++stackTop] = pMove;
               pMove = pMove->RChild;  //转到右边后,用同样的方法去找左边
               while(pMove)
               {
                    stack[++stackTop] = pMove;
                    pMove = pMove->LChild; 
               }
         }
     }
}


int  main()
{
     /*死板的创建方式,无实际作用,就是将结点连接起来而已*/
     LRTREE    A = createNode('A');
     LRTREE    B = createNode('B');
     LRTREE    C = createNode('C');
     LRTREE    D = createNode('D');
     LRTREE    E = createNode('E');
     LRTREE    F = createNode('F');
     LRTREE    G = createNode('G');
     insertNode(A , B ,C);
     insertNode(B , D ,NULL);
     insertNode(C , E ,F);
     
     printf("\n先序遍历:\n");
     preOrder(A);
     printf("\n");
     preOderByStack(A);

      printf("\n中序遍历:\n");
      midOrder(A);
      midOrderByStack(A);

     printf("\后序遍历:\n");
     lastOrder(A);
     lastOrderByStack(A);
     
     system("pause");
     return  0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值