二叉树的非递归遍历

建立二叉树后通过递归进行遍历时很简单   我们也可以通过合理的使用栈 和 队列进行  前中后 跟层序 遍历

#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;
            }
        }
    }
}


关注公众号 海量干货等你
原文地址:https://www.cnblogs.com/sowhat1412/p/12734404.html