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

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

   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:  }
posted @ 2013-07-29 09:38  winko  阅读(929)  评论(0编辑  收藏  举报