二叉树的遍历<递归算法实现>、<非递归算法实现>

来源:互联网 发布:淘宝可以买到美沙酮吗 编辑:程序博客网 时间:2024/06/11 05:10

二叉树的遍历主要有三种:前序遍历、中序遍历、后序遍历
下面以遍历下颗树为例:
前序遍历:-+a*b-cd/ef
中序遍历:a+b*c-d-e/f
后序遍历:abcd-*+ef/-
这里写图片描述

递归算法实现

public:    //前序遍历    void preOrder(void(*visit)(BinTreeNode<T> *p))    {        //递归算法        preOrder(root,visit);    }    //中序遍历    void inOrder(void(*visit)(BinTreeNode<T> *p))    {        inOrder(root,visit);    }    //后序遍历    void postOrder(void(*visit)(BinTreeNode<T> *p))    {        postOrder(root,visit);    }protected://前序遍历    void preOrder(BinTreeNode<T>*subTree,void(*visit)(BinTreeNode<T> *p))    {        if(subTree!=NULL)        {            visit(subTree);            preOrder(subTree->leftChild,visit);            preOrder(subTree->rightChild,visit);        }    }    //中序遍历    void inOrder(BinTreeNode<T> *subTree,void(*visit)(BinTreeNode<T> *p))    {        //递归函数,=NULL是终止递归条件        if(subTree!=NULL)        {            inOrder(subTree->leftChild,visit);            visit(subTree);//访问根节点            inOrder(subTree->rightChild,visit);        }    }    //后序遍历    void postOrder(BinTreeNode<T> *subTree,void(*visit)(BinTreeNode<T> *p))    {        if(subTree!=NULL)        {            postOrder(subTree->leftChild,visit);            postOrder(subTree->rightChild,visit);            visit(subTree);        }    }

非递归算法实现

//每一次访问一个节点后,在向左子树遍历下去之前,//利用这个栈记录该节点的右子女(如果有的话)节点地址,//以便左子树退回时可以直接从栈中取出右子树的根节点,继续其右子树的前序遍历    void preOrder(void(*visit)(BinTreeNode<T> *p))    {        stack<BinTreeNode<T> *> nodes;        BinTreeNode<T> *temp=root;        nodes.push(NULL);        while(temp!=NULL)        {            visit(temp);            if(temp->rightChild!=NULL)            {                nodes.push(temp->rightChild);            }            if(temp->leftChild!=NULL)            {                temp=temp->leftChild;            }            else            {                temp=nodes.top();                nodes.pop();            }        }    }    //中序遍历    //在一棵子树中首先访问的是中序下的第一个节点    //它位于从根开始的沿着leftchild链走到最左下角的节点,该节点的leftchild为NULL。    //访问完他的数据之后,再遍历它的右子树。如果此右子树又是二叉树,则重复上面的过程,直到该子树遍历完毕。    void inOrder(void(*visit)(BinTreeNode<T> *p))    {        stack<BinTreeNode<T> *> nodes;        //遍历指针,从根节点开始        BinTreeNode<T> *temp=root;        do        {            //遍历指针未到最左下的节点,不空            while(NULL!=temp)            {                //该子树沿途节点进栈                nodes.push(temp);                temp=temp->leftChild;            }            if(!nodes.empty())            {                //栈不为空的时候退栈,访问根节点,遍历指针进入右子女节点                temp=nodes.top();                visit(temp);                nodes.pop();                temp=temp->rightChild;            }        }        while(NULL!=temp||!nodes.empty());    }    //后序遍历    //后序遍历比先前的两种遍历要复杂得多,在遍历完左子树之后还不能访问根节点,    //需要再遍历右子树,等到右子树遍历完毕之后才能访问根节点。所以在栈工作记录中一定先表明刚才是在左子树<1>还是在右子树<2>中。    //首先使用栈暂存根节点的地址,再向左子树遍历下去,此时根节点的tag为1,当访问完根节点的左子树之后从左子树退回,还要去遍历右子树    //此时改跟的tag为2.    //从右子树中退出时才能访问位于栈顶的根节点的值。    void postOrder(void(*visit)(BinTreeNode<T> *p))    {        stack<stacknode<T> > nodes;        stacknode<T> temp;        BinTreeNode<T> *p=root;        do        {            while(NULL!=p)            {                temp.ptr=p;                temp.tag=1;                nodes.push(temp);                p=p->leftChild;            }            int continue1=1;            while(continue1&&!nodes.empty())            {                temp=nodes.top();                nodes.pop();                p=temp.ptr;                switch(temp.tag)                {                case 1:                    temp.tag=2;                    nodes.push(temp);                    continue1=0;                    p=p->rightChild;                    break;                case 2:                    visit(p);                    break;                }            }        }        while(!nodes.empty());    }    //层次遍历    //层次遍历从二叉树的根节点开始,自上向下,自左向右,分层依次访问树中的各个节点、    void levelOrder(void (*visit)(BinTreeNode<T> *p))    {        queue<BinTreeNode<T> *> nodes;        BinTreeNode<T> *temp=root;        BinTreeNode<T> *tnode;        nodes.push(temp);        while(!nodes.empty())        {            tnode=nodes.front();            nodes.pop();            visit(tnode);            if(NULL!=tnode->leftChild)            {                nodes.push(tnode->leftChild);            }            if(NULL!=tnode->rightChild)            {                nodes.push(tnode->rightChild);            }        }    }

需要整个工程的完整项目的朋友可以看我的这篇文章,点击进行跳转

0 0