二叉树前序,中序,后序的遍历【递归(借用栈实现)和非递归】

#include<iostream>
#include<cassert>
#include<stack>
using namespace std;
template<class T>
struct TreeNode
{
    T data;
    TreeNode<T>* left;
    TreeNode<T>* right;
    TreeNode(const T& x)
        :data(x)
        ,left(NULL)
        ,right(NULL)
    {}
};
template<class T>
class BinaryTree
{
    typedef TreeNode<T> Node;
public:
    BinaryTree(const T* arr,int sz,const T& invalib)//1.构造函数---前序构造二叉树
    {
        assert(arr);
        int index=0;
        _root=CreatTree(arr,sz,invalib,index);
    }
    ~BinaryTree()//2.析构函数
    {
        Destroy(_root);//销毁一颗二叉树
        _root=NULL;
    }
    void PreOrder()//6.前序遍历打印(递归)
    {
        _PreOrder(_root);
    }
    void InOrder()//7.中序遍历打印(递归)
    {
        _InOrder(_root);
    }
    void EndOrder()//8.后序遍历打印(递归)
    {
        _EndOrder(_root);
    }
    void PreOrderNO()//10.前序遍历打印(非递归)
    {
        _PreOrder(_root);
    }
    void InOrderNO()//11.中序遍历打印(非递归)
    {
        _InOrderNO(_root);
    }
    void EndOrderNO()//12.后序遍历打印(非递归)
    {
        _EndOrderNO(_root);
    }
protected:
    Node* CreatTree(const T* arr,int sz,const T& invalib,int& index)//前序构造二叉树
    {
        assert(arr);
        Node* root=NULL;
        while (index<sz&&arr[index]!=invalib)
        {
            root=new Node(arr[index]);
            root->left=CreatTree(arr,sz,invalib,++index);//此处index必须前置++
            root->right=CreatTree(arr,sz,invalib,++index);//此处index必须前置++
        }
        return root;
    }
    void Destroy(Node* root)//销毁一颗二叉树
    {
        //1.树为空,直接返回,无结点销毁
        if (root==NULL)
        {
            return ;
        }
        //2.树只有一个结点,则销毁该节点
        if (root->left==NULL&&root->right==NULL)
        {
            delete root;
            root=NULL;
            return;
        }
        //3.树的结点大于一个,则先销毁左子树,后销毁右子树
        Destroy(root->left);
        Destroy(root->right);
        delete root;
        root=NULL;
    }


----------

    void _PreOrder(Node* root)//前序遍历打印(递归):根->左->右
    {
        //1.根结点为空,二叉树为空,直接返回---递归返回条件
       if (root==NULL)
       {
           return ;
       }

       //2.根结点不为空,先打印根结点,在打印左子树,后打印右子树
       cout<<root->data<<" ";
       _PreOrder(root->left);
       _PreOrder(root->right);
    }


----------


    void _InOrder(Node* root)//中序遍历打印(递归):左->根->右
    {
        //1.根结为空,二叉树没有结点---递归返回条件
        if (root==NULL)
        {
            return ;
        }
        //2.根结点不为空,二叉树有节点
        _InOrder(root->left);
        cout<<root->data<<" ";
        _InOrder(root->right);
    }


----------


    void _EndOrder(Node* root)//后序遍历打印(递归):左->右->根
    {
        //1.根结点为空,二叉树没有结点---递归返回条件
        if (root==NULL)
        {
            return ;
        }
        //2.根结点不为空,二叉树有节点
        _EndOrder(root->left);
        _EndOrder(root->right);
        cout<<root->data<<" ";
    }


----------

    void _PreOrderNO(Node* root)//前序遍历打印(非递归)---用栈实现(根左右)
    {
       stack<Node*>  s;
       Node* cur=root;
       while (cur||!s.empty())
       {
           while (cur)
           {
               s.push(cur);
               cout<<cur->data<<" ";
               cur=cur->left;
           }
           //top从栈中取出来,表示以这个结点为根结点的树的左子树已经访问完了,
           //剩余右子树还没有访问,循环子问题访问右树
           Node* top=s.top();
           s.pop();
           //子问题的方式访问右树
           cur=top->right;
       }
    }


----------


    void _InOrderNO(Node* root)//中序遍历打印(非递归)---用栈实现(左根右)
    {
          stack<Node*> s;
          Node* cur=root;
          while (cur||!s.empty())
          {
              while (cur)
              {
                  s.push(cur);
                  cur=cur->left;
              }
              Node* top=s.top();
              cout<<top->data<<" ";
              //表示左子树和根结点已经访问完了,剩下右子树没有访问,循环子问题访问右树
              s.pop();
              //循环子问题访问右树
              cur=top->right;
          }
    }


----------


    void _EndOrderNO(Node* root)//后序遍历打印(非递归)---用栈实现(左右根)
    {
          stack<Node*>  s;
          Node* cur=root;
          Node* prev=NULL;//记录已经访问过的结点
          while (cur||!s.empty())
          {
              while (cur)
              {
                  s.push(cur);
                  cur=cur->left;
              }
              Node* top=s.top();
              //如果该根结点的右子树已经访问过了或者右子树为空,那么直接访问该根结点,
              //然后更新prev,从栈中pop掉该节点
              if (prev==top->right||top->right==NULL)
              {
                  cout<<top->data<<" ";
                  s.pop();
                  prev=top;
              }
              如果该根结点的右子树没有访问过了或者右子树为不为空
              循环更新cur,循环子问题访问右子树
              else
              {
                  cur=top->right;
              }

          }
    }
protected:
    Node* _root;
};

int main()
{
    int arr[]={1,2,3,'#','#',4,'#','#',5,6,'#','#','#'};
    int sz=sizeof(arr)/sizeof(arr[0]);
    BinaryTree<int>  bt(arr,sz,'#');

    cout<<"前序打印【递归】";
    bt.PreOrder();
    cout<<endl;

    cout<<"中序打印【递归】";
    bt.InOrder();
    cout<<endl;

    cout<<"后序打印【递归】";
    bt.EndOrder();
    cout<<endl;

    cout<<"前序打印【非递归】";
    bt.PreOrderNO();
    cout<<endl;

    cout<<"中序打印【非递归】";
    bt.InOrderNO();
    cout<<endl;


    cout<<"后序打印【非递归】";
    bt.EndOrderNO();
    cout<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值