建立二叉树后通过递归进行遍历时很简单 我们也可以通过合理的使用栈 和 队列进行 前中后 跟层序 遍历
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
typedef struct treenode
{
int data;
struct treenode * left;
struct treenode* right;
}TREE_NODE;
typedef struct T_N
{
TREE_NODE* root;
int size;
}TREE;
void PreOrderTraverse(TREE_NODE* root)
{
if(root)
{
cout<<root->data<<" ";
PreOrderTraverse(root->left);
PreOrderTraverse(root->right);
}
}
void InOrderTraverse(TREE_NODE* root)
{
if(root)
{
InOrderTraverse(root->left);
cout<<root->data<<" ";
InOrderTraverse(root->right);
}
}
void PostOrderTraverse(TREE_NODE* root)
{
if(root)
{
PostOrderTraverse(root->left);
PostOrderTraverse(root->right);
cout<<root->data<<" ";
}
}
void printTreeByLevel(TREE_NODE* root) //层序遍历
{
if(NULL == root)
{
return;
}
vector<TREE_NODE*>tempVector;
tempVector.push_back(root);
int cur=0;
while(cur<tempVector.size())
{
cout<<tempVector[cur]->data<<" ";
if(tempVector[cur]->left != NULL)
{
tempVector.push_back(tempVector[cur]->left);
}
if(tempVector[cur]->right !=NULL)
{
tempVector.push_back(tempVector[cur]->right);
}
cur++;
}
cout<<endl;
}
我们先考虑中序遍历的非递归形式,顺序是 左 根 右 这个时用到了 栈 先入后出
我们一定是先找到最左边的叶子节点
if(NULL == root)
{
return;
}
stack<TREE_NODE*>tempS;
while(root)
{
tempS.push(root);
root = root->left;
}
保存一路走过的根节点的理由是:中序遍历的需要,遍历完左子树后,需要借助根节点进入右子树。代码走到这里,指针p为空,此时无非两种情况:
我们的思维接着走,两图情形不同得区别对待: 1.图a中访问的是一个左孩子,按中序遍历顺序,接下来应访问它的根节点。也就是图a中的另一个节点,高兴的是它已被保存在栈中。我们只需这样的代码和上一步一样的代码:
void InOrderPrint(TREE_NODE* root) //中序遍历 理解下思想 就不难了
{
if(NULL == root)
{
return;
}
stack<TREE_NODE*>tempS;
while(!tempS.empty() || root)// 理解为什么这样写 tempS.empty()是为了输出全部用的
{
if(root)
{
tempS.push(root);
root = root->left;
}
else
{
root = tempS.top();
tempS.pop();
cout<<root->data<<" ";
root = root->right;
}
}
}
void InOrderTraverse(TREE_NODE* root)
{
if(root)
{
InOrderTraverse(root->left);
cout<<root->data<<" ";
InOrderTraverse(root->right);
}
}
对于前序遍历一样 的情况 类似 分析后直接给出代码
void PreOrderTraverse(TREE_NODE* root)
{
if(root)
{
cout<<root->data<<" ";
PreOrderTraverse(root->left);
PreOrderTraverse(root->right);
}
}
void PreOrderPrint(TREE_NODE *root)
{
if(NULL == root)
{
return;
}
stack<TREE_NODE*>tempS;
while(!tempS.empty() || root)
{
if(root)
{
cout<<root->data<<" ";
tempS.push(root);
root = root->left;
}
else
{
root = tempS.top();
tempS.pop();
root = root->right;
}
}
}
后序遍历
分析
后序遍历递归定义:先左子树,后右子树,再根节点。后序遍历的难点在于:需要判断上次访问的节点是位于左子树,还是右子树。若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点;若是位于右子树,则直接访问根节点。直接看代码,代码中有详细的注释。
void PostOrderTraverse(TREE_NODE* root)
{
if(root)
{
PostOrderTraverse(root->left);
PostOrderTraverse(root->right);
cout<<root->data<<" ";
}
}
void PostOrderPrint(TREE_NODE* root)
{
if(NULL == root)
{
return ;
}
stack<TREE_NODE*>tempS;
TREE_NODE* front = NULL;
while(root)
{
tempS.push(root);
root = root->left;
}//照样先找到最左边的根节点
while(! tempS.empty())
{
root = tempS.top(); //因为上面while 循环后root 为空 此时要先取出 最左边的root
tempS.pop();
if(root->right == NULL || root->right == front)// 一个根节点被访问的前提是:无右子树或右子树已被访问过
{
cout << root->data << " ";
front = root;
}
else
{
tempS.push(root); // 还要把该点入栈 然后 打出右子树
root = root->right; //进入右子树,且肯定右子树一定不为空
while(root)
{
tempS.push(root);
root = root->left;
}
}
}
}