• 二叉树的非递归遍历(栈)


    二叉树递归遍历很简单,如先序遍历:

       1:  void preOrder(Tree T)
       2:  {
       3:      if (T!=NULL)
       4:      {
       5:          cout<<T->element<<" ";
       6:          preOrder(T->left);
       7:          preOrder(T->right);
       8:      }
       9:  }

    递归过程很简单,可以从二叉树的图结构看出,T一直左走,直到null,然后返回父节点,以其右子节点为根,重复步骤。

    因此,需要有个方法,能够返回当前节点的父节点,即能够回溯

    有两种方法:方法见此博客

    1.使用栈的记忆

    两个版本:模拟递归的实现效果;模拟后序遍历入栈。

    2.增加一个指向父节点的指针。

    其中,本文主要用栈结构实现非递归遍历。

    其中,由于前序与中序遍历的情况,有节点序列的连续,因此,采用模拟递归的方法较容易;而后序遍历根节点有一定的跳跃性,需要先访问左,然后跳至右节点,最后才访问中间节点,使用模拟后序入栈的顺序遍历方法时,需要一个变量来标记中间节点的访问。

    前序遍历与中序遍历的模拟递归实现:

       1:  #include <stack>
       2:  //前序遍历二叉搜索树:用栈模拟递归
       3:  void PreOrderTraversal(Tree T)
       4:  {
       5:      stack<Tree> s;
       6:      while (NULL!=T || !(s.size()==0))
       7:      {
       8:          if (T!=NULL)
       9:          {
      10:              cout<<T->element<<" ";//前序遍历,先处理根节点
      11:              s.push(T);//入栈
      12:              T=T->left;//一直向左搜索,若非空则入栈
      13:          }
      14:          else
      15:          {
      16:              T = s.top();//回溯到父节点
      17:              s.pop();
      18:              T = T->right;//以父节点的右子节点为新的根节点,重复上述一直向左搜索操作
      19:          }
      20:      }
      21:      cout<<endl;
      22:  }
      23:   
      24:  void InOrderTraversal(Tree T)
      25:  {
      26:      stack<Tree> s;
      27:      while(T!=NULL || !s.empty())
      28:      {
      29:          if (T!=NULL)
      30:          {
      31:              s.push(T);
      32:              T=T->left;
      33:          }
      34:          else
      35:          {
      36:              T = s.top();
      37:              s.pop();
      38:              cout<<T->element<<" ";
      39:              T=T->right;
      40:          }
      41:      }
      42:      cout<<endl;
      43:  }

    后序遍历的非递归模拟后序入栈顺序实现:

       1:  //后序遍历二叉搜索树:非递归方法,使用栈(模拟后序)
       2:  void PostOrderTraversal(Tree T)
       3:  {
       4:      if (NULL==T)
       5:      {
       6:          cout<<"NULL trees"<<endl;
       7:      }
       8:      stack<Tree> s;
       9:      T->bPushed = false;//bPushed:表示左右子节点是否已经入栈。
      10:                         //初始化为false,表示还未处理左右子节点
      11:      s.push(T);
      12:      
      13:      while (!s.empty())
      14:      {
      15:          T = s.top();
      16:          s.pop();
      17:          if (T->bPushed==true)
      18:          {//bPushed:为true,表示左右子节点均已入栈。此时,访问该节点。
      19:           //bPushed的使用可避免左右子节点重复入栈:false,表示左右子节点需入栈;true的话,直接跳过
      20:              cout<<T->element<<" ";
      21:          }
      22:          else
      23:          {//bPushed:为false。此时,需设置bPushed为true,然后处理左右子节点。
      24:              T->bPushed = true;//设置该节点标志符为true,然后处理左右子节点。
      25:              s.push(T);
      26:   
      27:              if (T->right!=NULL )
      28:              {
      29:                  T->right->bPushed = false;//初始化当前节点的右节点(若存在)为false
      30:                  s.push(T->right);
      31:              }
      32:   
      33:              if (T->left!=NULL )
      34:              {
      35:                  T->left->bPushed = false;//初始化当前节点的左节点(若存在)为false
      36:                  s.push(T->left);
      37:              }
      38:   
      39:          }
      40:      }
      41:      cout<<endl;
      42:  }

    完整程序:

       1:  typedef struct TreeNode * Tree;
       2:  typedef int ElemType;
       3:  struct TreeNode
       4:  {
       5:      ElemType element;
       6:      Tree left;
       7:      Tree right;
       8:      bool bPushed;
       9:  };
      10:  #include <iostream>
      11:  using namespace std;
      12:   
      13:   
      14:  //创建一个空树
      15:  Tree MakeEmpty(Tree T)
      16:  {
      17:      if (NULL!=T)
      18:      {
      19:          MakeEmpty(T->left);
      20:          MakeEmpty(T->right);
      21:          free(T);
      22:      }
      23:      return NULL;
      24:  }
      25:   
      26:  Tree Insert(ElemType X,Tree& T)
      27:  {
      28:      if (NULL==T)
      29:      {
      30:          T = (Tree)malloc(sizeof(TreeNode));
      31:          if (NULL==T)
      32:          {
      33:              cout<<"out of space!"<<endl;
      34:          }
      35:          else
      36:          {
      37:              T->element = X;
      38:              T->left=NULL;
      39:              T->right=NULL;
      40:          }
      41:          return T;
      42:      }
      43:      else
      44:      {
      45:          if (X<T->element)
      46:          {
      47:              T->left = Insert(X,T->left);
      48:          }
      49:          else
      50:              T->right = Insert(X,T->right);
      51:      }
      52:      return T;
      53:  }
      54:   
      55:  #include <stack>
      56:  //前序遍历二叉搜索树:用栈模拟递归
      57:  void PreOrderTraversal(Tree T)
      58:  {
      59:      stack<Tree> s;
      60:      while (NULL!=T || !(s.size()==0))
      61:      {
      62:          if (T!=NULL)
      63:          {
      64:              cout<<T->element<<" ";//前序遍历,先处理根节点
      65:              s.push(T);//入栈
      66:              T=T->left;//一直向左搜索,若非空则入栈
      67:          }
      68:          else
      69:          {
      70:              T = s.top();//回溯到父节点
      71:              s.pop();
      72:              T = T->right;//以父节点的右子节点为新的根节点,重复上述一直向左搜索操作
      73:          }
      74:      }
      75:      cout<<endl;
      76:  }
      77:   
      78:  void InOrderTraversal(Tree T)
      79:  {
      80:      stack<Tree> s;
      81:      while(T!=NULL || !s.empty())
      82:      {
      83:          if (T!=NULL)
      84:          {
      85:              s.push(T);
      86:              T=T->left;
      87:          }
      88:          else
      89:          {
      90:              T = s.top();
      91:              s.pop();
      92:              cout<<T->element<<" ";
      93:              T=T->right;
      94:          }
      95:      }
      96:      cout<<endl;
      97:  }
      98:   
      99:  //后序遍历二叉搜索树:非递归方法,使用栈(模拟后序)
     100:  void PostOrderTraversal(Tree T)
     101:  {
     102:      if (NULL==T)
     103:      {
     104:          cout<<"NULL trees"<<endl;
     105:      }
     106:      stack<Tree> s;
     107:      T->bPushed = false;//bPushed:表示左右子节点是否已经入栈。
     108:                         //初始化为false,表示还未处理左右子节点
     109:      s.push(T);
     110:      
     111:      while (!s.empty())
     112:      {
     113:          T = s.top();
     114:          s.pop();
     115:          if (T->bPushed==true)
     116:          {//bPushed:为true,表示左右子节点均已入栈。此时,访问该节点。
     117:           //bPushed的使用可避免左右子节点重复入栈:false,表示左右子节点需入栈;true的话,直接跳过
     118:              cout<<T->element<<" ";
     119:          }
     120:          else
     121:          {//bPushed:为false。此时,需设置bPushed为true,然后处理左右子节点。
     122:              T->bPushed = true;//设置该节点标志符为true,然后处理左右子节点。
     123:              s.push(T);
     124:   
     125:              if (T->right!=NULL )
     126:              {
     127:                  T->right->bPushed = false;//初始化当前节点的右节点(若存在)为false
     128:                  s.push(T->right);
     129:              }
     130:   
     131:              if (T->left!=NULL )
     132:              {
     133:                  T->left->bPushed = false;//初始化当前节点的左节点(若存在)为false
     134:                  s.push(T->left);
     135:              }
     136:   
     137:          }
     138:      }
     139:      cout<<endl;
     140:  }
     141:   
     142:  void preOrder(Tree T)
     143:  {
     144:      if (T!=NULL)
     145:      {
     146:          cout<<T->element<<" ";
     147:          preOrder(T->left);
     148:          preOrder(T->right);
     149:      }
     150:  }
     151:   
     152:  void inOrder(Tree T)
     153:  {
     154:      if (T!=NULL)
     155:      {
     156:          inOrder(T->left);
     157:          cout<<T->element<<" ";
     158:          inOrder(T->right);
     159:      }
     160:  }
     161:   
     162:  void postOrder(Tree T)
     163:  {
     164:      if (T!=NULL)
     165:      {
     166:          postOrder(T->left);
     167:          postOrder(T->right);
     168:          cout<<T->element<<" ";
     169:      }
     170:  }
     171:  int main()
     172:  {
     173:   
     174:      Tree T = NULL;
     175:      Insert(10,T);
     176:      Insert(20,T);
     177:      Insert(8,T);
     178:      Insert(15,T);
     179:      Insert(1,T);
     180:      Insert(9,T);
     181:      Insert(28,T);
     182:      preOrder(T);cout<<endl;
     183:      inOrder(T);cout<<endl;
     184:      postOrder(T);cout<<endl;
     185:      PreOrderTraversal(T);
     186:      InOrderTraversal(T);
     187:      PostOrderTraversal(T);
     188:      system("pause");
     189:      return 0;
     190:  }
  • 相关阅读:
    PHP 使用命名空间(namespace),实现自动加载
    快捷方式不能使用的解决方法
    Python学习案例
    Linux下Tomcat的安装和部署
    关于Linux下的环境变量
    关于Linux下安装Oracle
    Linux下安装MySQLdb模块(Python)
    交换机VLAN的定义、意义以及划分方式
    让java程序在后台一直执行(例如putty关闭后后台程序继续运行)
    基于FTP服务器搭建yum源
  • 原文地址:https://www.cnblogs.com/baiweiguo/p/3222281.html
Copyright © 2020-2023  润新知