二叉树的遍历---递归和非递归实现

1.二叉树遍历—递归实现
- 先序遍历—递归实现

void PreOrder()//先序遍历   根-->左子树-->右子树
    {
        cout<<"PreOrder: ";
        _PreOrder(_pRoot);
        cout<<endl;
    }
  • 中序遍历—递归实现
void InOrder()//中序遍历  左子数--》根--》右子树
    {
        cout<<"InOrder: ";
        _InOrder(_pRoot);
        cout<<endl;
    }
  • 后序遍历递归实现
void PostOrder()//后序遍历  左子树--》右子树--》根
    {
        cout<<"PostOrder: ";
        _PostOrder(_pRoot);
        cout<<endl;
    }
  • 层序遍历
void LevelOrder()//层序遍历
    {
        cout<<"LevelOrder: ";
        _LevelOrder(_pRoot);
        cout<<endl;
    }
    void _LevelOrder(Node* pRoot)//层序遍历
    {
        if(pRoot!=NULL)
        {
            queue<Node*> q;
            q.push(pRoot);

            Node*pCur = NULL;
            while(!q.empty())
            {
                pCur = q.front();
                cout<<pCur->_data<<" ";
                if(pCur->_pLeft)
                    q.push(pCur->_pLeft);
                if(pCur->_pRight)
                    q.push(pCur->_pRight);
                q.pop();
            }
        }
    }

2.二叉树遍历—非递归实现

  • 先序遍历—非递归实现(三种实现方法)

    1. 实先序遍历现1:访问子树时用栈保存数据,再左右子树存在的情况下,先保存左子树,再保存右子树
void PreOrder_Nor()//先序遍历--循环
    {
        cout<<"PreOrder_Nor: ";
        _PreOrder_Nor(_pRoot);
        cout<<endl;
    }
        void _PreOrder_Nor(Node* pRoot)//前序遍历--循环--实现1(栈中保存的是根)
    {
        if(pRoot==NULL)
            return;
        stack<Node*> s;
        s.push(pRoot);
        while(!s.empty())
        {
            Node* pCur = s.top();
            cout<<pCur->_data<<" ";
            s.pop();//访问完后必须立即出栈,因为栈是先进后出的,所以不能再右左孩子入栈之后再出栈

            if(pCur->_pRight != NULL)
            s.push(pCur->_pRight);
            if(pCur->_pLeft != NULL)
            s.push(pCur->_pLeft);
        }
    }

2.先序遍历实现2:

void PreOrder_Nor1()//先序遍历--循环
    {
        cout<<"PreOrder_Nor: ";
        _PreOrder_Nor1(_pRoot);
        cout<<endl;
void _PreOrder_Nor1(Node* pRoot)//先序遍历--循环--实现2(先将左子树全部访问并入栈,再依次出栈访问右子树)
    {
        if(pRoot==NULL)
            return;
        stack<Node*> s;
        Node* pCur = pRoot;
        Node* pRev = NULL;
        while(pCur!=NULL || !s.empty())
        {
            while(pCur!=NULL)
            {
                s.push(pCur);
                cout<<pCur->_data<<" ";
                pCur = pCur->_pLeft;
            }
            pCur = s.top();
            if(pCur->_pRight==NULL || pRev==pCur->_pRight)
            {
                pRev = pCur;
                s.pop();
                pCur = NULL;
            }
            else
            {
                pCur = pCur->_pRight;
            }
        }
    }

3.先序遍历实现3:先将根入栈入栈并访问,保存右子树,访问左子树

void PreOrder_Nor2()//先序遍历--循环(实现3,先将根入栈入栈并访问,保存右子树,访问左子树)
    {
        cout<<"PreOrder_Nor: ";
        _PreOrder_Nor2(_pRoot);
        cout<<endl;
    }
    void _PreOrder_Nor2(Node* pRoot)//先序遍历--循环--实现2(访问左子树,保存右子树,当左子树都访问完后,再从栈中取右节点访问)
    {
        if(pRoot==NULL)
            return;
        stack<Node*> s;
        Node* pCur = pRoot;
        while(!s.empty() || pCur)
        {
            while(pCur)
            {
                cout<<pCur->_data<<" ";
                if(pCur->_pRight)
                    s.push(pCur->_pRight);//保存右节点是为了再访问完根节点和左子树是能够找到右子树,每次保存一个右子树,访问完后立即出栈,为了保存下一个左子树
                pCur = pCur->_pLeft;
            }
            if(!s.empty())
            {
                pCur = s.top();
                s.pop();
            }
        }
    }
  • 中序遍历—循环实现
void InOrder_Nor()//中序遍历--循环
    {
        cout<<"InOrder_Nor: ";
        _InOrder_Nor(_pRoot);
        cout<<endl;
    }
void  _InOrder_Nor(Node* pRoot)//中序遍历---循环
    {
        if(pRoot == NULL)
            return;
        stack<Node*> s;
        Node* pCur = pRoot;
        while(pCur!=NULL || !s.empty())
        {
            while(pCur!=NULL)//找到最左的节点
            {
                s.push(pCur);
                pCur = pCur->_pLeft;
            }
            pCur = s.top();
            cout<<pCur->_data<<" ";
            s.pop();

            //pCur = pCur->_pRight; //不区分的时候

            while(pCur->_pRight == NULL && !s.empty())//当右子树的节点为NULL时,不断出栈
            {
                pCur = s.top();
                cout<<pCur->_data<<" ";
                s.pop();
            }
            pCur = pCur->_pRight;
        }
    }
  • 后序遍历—循环实现
void PostOrder_Nor()//后序遍历--循环
    {
        cout<<"PostOrder_Nor: ";
        _PostOrder_Nor(_pRoot);
        cout<<endl;
    }
void _PostOrder_Nor(Node* pRoot)//后续遍历---循环
    {
        if(pRoot==NULL)
            return;
        stack<Node*> s;
        Node* pCur = _pRoot;
        Node* pRev = NULL;//标记该节点是否访问过
        while(!s.empty() || pCur!=NULL)
        {
            while(pCur!=NULL)
            {
                s.push(pCur);
                pCur = pCur->_pLeft;
            }
            pCur = s.top();
            if(pCur->_pRight==NULL || pRev==pCur->_pRight)
            {
                cout<<pCur->_data<<" ";
                pRev = pCur;
                s.pop();
                pCur = NULL;
            }
            else
            {
                pCur = pCur->_pRight;
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值