• 二叉树的遍历的迭代和递归实现方式


    二叉树是一种非常重要的数据结构,很多其它数据结构都是基于二叉树的基础演变而来的。对于二叉树,有前序、中序以及后序三种遍历方法。因为树的定义本身就是递归定义,因此采用递归的方法去实现树的三种遍历不仅容易理解而且代码很简洁。而对于树的遍历若采用非递归的方法,就要采用栈去模拟实现。在三种遍历中,前序和中序遍历的非递归算法都很容易实现,非递归后序遍历实现起来相对来说要难一点。

    一.前序遍历

       前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。

       1.递归实现

    复制代码
    void preOrder1(BinTree *root)     //递归前序遍历 {
        if(root!=NULL)
        {
            cout<<root->data<<"";
            preOrder1(root->lchild);
            preOrder1(root->rchild);
        }
    }
    复制代码

       2.非递归实现

        根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:

         对于任一结点P:

         1)访问结点P,并将结点P入栈;

         2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;

         3)直到P为NULL并且栈为空,则遍历结束。

    复制代码
    void preOrder2(BinTree *root)     //非递归前序遍历 {
        stack<BinTree*> s;
        BinTree *p=root;
        while(p!=NULL||!s.empty())
        {
            while(p!=NULL)
            {
                cout<<p->data<<"";
                s.push(p);
                p=p->lchild;
            }
            if(!s.empty())
            {
                p=s.top();
                s.pop();
                p=p->rchild;
            }
        }
    }
    复制代码

    二.中序遍历

        中序遍历按照“左孩子-根结点-右孩子”的顺序进行访问。

        1.递归实现

    复制代码
    void inOrder1(BinTree *root)      //递归中序遍历{
        if(root!=NULL)
        {
            inOrder1(root->lchild);
            cout<<root->data<<"";
            inOrder1(root->rchild);
        }
    } 
    复制代码

       2.非递归实现

        根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点,直到遇到左孩子结点为空的结点才进行访问,然后按相同的规则访问其右子树。因此其处理过程如下:

       对于任一结点P,

      1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;

      2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;

      3)直到P为NULL并且栈为空则遍历结束

    复制代码
    void inOrder2(BinTree *root)      //非递归中序遍历{
        stack<BinTree*> s;
        BinTree *p=root;
        while(p!=NULL||!s.empty())
        {
            while(p!=NULL)
            {
                s.push(p);
                p=p->lchild;
            }
            if(!s.empty())
            {
                p=s.top();
                cout<<p->data<<"";
                s.pop();
                p=p->rchild;
            }
        }    
    } 
    复制代码

      三.后序遍历

          后序遍历按照“左孩子-右孩子-根结点”的顺序进行访问。

          1.递归实现

    复制代码
    void postOrder1(BinTree *root)    //递归后序遍历{
        if(root!=NULL)
        {
            postOrder1(root->lchild);
            postOrder1(root->rchild);
            cout<<root->data<<"";
        }    
    } 
    复制代码
        2.迭代实现
    先找到最左边的叶子并把路上遇到的节点一次进栈,然后弹出栈顶的元素(该元素为最左边的叶子)并判断(1)它有没有右节点;
    (2)右节点是否被访问过;如果有右节点同时没被访问过,则先压入刚才弹出的元素,然后压入它的右子树,否则访问该节点并设置pre为该节点。
    void postOrder2(BinTree *root) //非递归后序遍历
    {
        stack<BinTree*> s;
        BinTree *p=root;
        BinTree *pre=NULL;
        BinTree *top=NULL;
        while(p!=NULL||!s.empty())
        {
            while(p!=NULL)
            {
                s.push(p);
                p=p->lchild;
            }
            if(!s.empty())
            {
                top=s.top();
                if(top->right!=NULL&&top->right!=pre)
                {
                    p=p->right;
                }
                else
                {
                    cout<<top->data<<" "
                    pre=top;
                    s.pop()  
                } 
            }
        }    
    }
  • 相关阅读:
    BZOJ3498PA2009 Cakes——三元环
    黑科技之三元环讲解
    BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)
    BZOJ2463[中山市选2009]谁能赢呢?——博弈论
    BZOJ2275[Coci2010]HRPA——斐波那契博弈
    BZOJ2281[Sdoi2011]黑白棋&BZOJ4550小奇的博弈——DP+nimk游戏
    BZOJ3435[Wc2014]紫荆花之恋——动态点分治(替罪羊式点分树套替罪羊树)
    Trie树学习总结
    kmp学习小结
    Hash学习小结
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3230925.html
Copyright © 2020-2023  润新知