精华内容
下载资源
问答
  • 非递归后序遍历二叉树的方式实现的表达式计算,进行了精细的表达式逻辑判断和处理,可进行加减乘除、括号、小数的计算。项目结构清晰,基本都有代码注释,可用于数据结构实验。同为学习人,能力有限,不足之处还请...
  • 前序、中序、后序非递归遍历中,要数后序最为麻烦,如果只在栈中保留指向结点的指针,那是不够的,必须有一些额外的信息存放在栈中。方法有很多,这里只举一种,先定义栈结点的数据结构 代码如下:typedef struct{...
  • 主要为大家详细介绍了C语言非递归后序遍历二叉树,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 主要介绍了C语言数据结构之二叉树的非递归后序遍历算法的相关资料,希望通过本文能帮助到大家,让大家实现这样的功能,需要的朋友可以参考下
  • 非递归后序遍历

    2021-02-05 18:36:21
    非递归后序遍历

    树的后序遍历特点:

    思路1:先序特点+逆序输出

    先序遍历特点:
    在先序非递归遍历代码的基础上可以实现:
    如果逆序输出,就是:

    于是我们需要一个另外的栈用来逆序输出。

    template<class T>
    void BinaryTree<T>::PostOrder()					//后序遍历
    {
    	LinkStack<BiTreeNode<T>*>S;
    	LinkStack<BiTreeNode<T>*>S2;				//用来逆序输出
    	if (root == NULL)
    	{
    		return;
    	}
    	S.Push(root);
    	BiTreeNode<T>* q = root;
    	while (!S.Is_Empty())
    	{
    		S.Pop(q);
    		S2.Push(q);
    		if (q->leftChild)
    		{
    			S.Push(q->leftChild);
    		}
    		if (q->rightChild)
    		{
    			S.Push(q->rightChild);
    		}
    	}
    	while (!S2.Is_Empty())
    	{
    		S2.Pop(q);
    		cout << q->data << " ";
    	}
    }
    

    思路2:先访问左右孩子,再访问父亲

    1.若结点不空且左右孩子未被访问,记录结点,并指向左孩子
    2.否则 如果右子树不空且右孩子未被访问,指向右孩子
    3. ——否则访问栈顶

    template<class T>
    void BinaryTree<T>::PostOrder()					//后序遍历
    {
    	LinkStack<BiTreeNode<T>*>S;
    	BiTreeNode<T>* pre = root;							//记录上一次访问的结点
    	BiTreeNode<T>* p = root;							//记录当前访问结点
    	while (p || !S.Is_Empty())
    	{
    		if (p != NULL && pre != p->leftChild && pre != p->rightChild)		//结点不空且左右孩子未被访问
    		{
    			S.Push(p);
    			p = p->leftChild;
    		}
    		else
    		{
    			S.Get_Top(p);
    			if (p->rightChild != NULL && pre != p->rightChild)		//右子树不空且没被访问,入栈右孩子
    			{
    				p = p->rightChild;
    			}
    			else													//访问到最后的右子树的结点后,退栈
    			{
    				S.Pop(pre);
    				cout << pre->data << " ";
    				if (!S.Get_Top(p))
    				{
    					p = NULL;
    				}
    			}
    		}
    	}
    }
    
    展开全文
  • 利用栈实现非遍历文件目录
  • //C++实现链式二叉树,采用非递归的方式先序,中序,后序遍历二叉树#include “stdafx.h”#include<iostream>#include<string>#include <stack>using namespace std;template<class>struct BiNode{ T data; struct...
  • //二叉链表: 递归、非递归(非递归用栈)先序、中序、后序遍历(非递归后序遍历麻烦点,需要用到flag标志) //以及层序遍历(层序用队列),以及建立在遍历上的一些操作 //思考:对二叉链表的操作几乎都是建立在...
    //严蔚敏《数据结构》
    //二叉链表: 递归、非递归(非递归用栈)先序、中序、后序遍历(非递归后序遍历麻烦点,需要用到flag标志)
    //以及层序遍历(层序用队列),以及建立在遍历上的一些操作
    
    //思考:对二叉链表的操作几乎都是建立在遍历的基础上(所以说遍历很重要!!)
    //若为简单的输出遍历,递归容易实现,但效率较低;
    //若不是简单的输出,是建立在遍历基础上的一些操作,比如 寻找双亲,非递归容易实现
    //5-7行是基于现在水平的我的理解,可能不太对,我会回来的
    
    //自学中,加油!!!
    #include<iostream>
    using namespace std;
    #define TElemType double
    
    typedef struct BiTNode
    {
        TElemType data;
        struct BiTNode* lchild,* rchild;
        int flag;//标志变量 标志非递归的后序遍历
    }BiTNode,* BiTree;
    
    bool Creat_BiTree(BiTree& T)//递归先序创建并输入
    {
        TElemType num;
        if(cin>>num){//此处应用if而不是while循环  这是在用递归,就不用while循环了
            T=new BiTNode;
            if(!T)
                return false;
            T->data=num;
            Creat_BiTree(T->lchild);
            Creat_BiTree(T->rchild);
        }
        if(!cin)
            T=nullptr;
        if(!cin){
            cin.clear();
            while(cin.get()!='\n')
                continue;
        }
        return true;
    }
    
    void PreOrder_Bitree(BiTree T)//递归先序遍历
    {
        if(T){
            cout<<T->data<<endl;
            PreOrder_Bitree(T->lchild);
            PreOrder_Bitree(T->rchild);
        }
    }
    
    void InOrder_bitree(BiTree T)//递归中序遍历
    {
        if(T){
            InOrder_bitree(T->lchild);
            cout<<T->data<<endl;
            InOrder_bitree(T->rchild);
        }
    }
    
    void PostOrder_BiTree(BiTree T)//递归后序遍历
    {
        if(T){
            PostOrder_BiTree(T->lchild);
            PostOrder_BiTree(T->rchild);
            cout<<T->data<<endl;
        }
    }
    //构造的队列为层序遍历服务
    #define QElemType BiTree
    typedef struct QNode
    {
        QElemType data;
        struct QNode* next;
    }QNode,* QPtr;
    
    typedef struct
    {
        QPtr head,tail;
        int length;
    }QueueList;
    
    bool Init_Queue(QueueList& Q)
    {
        Q.head=new QNode;
        if(!Q.head)
            return false;
        Q.head->next=nullptr;
        Q.tail=Q.head;
        Q.length=0;
        return true;
    }
    
    bool IsEmpty_Queue(QueueList Q)
    {
        if(Q.length)
            return false;
        return true;
    }
    
    bool Push_Queue(QueueList& Q,QElemType e)
    {
        QPtr p=new QNode;
        if(!p)
            return false;
        p->data=e;
        p->next=Q.tail->next;
        Q.tail->next=p;
        Q.tail=p;
        Q.length++;
        return true;
    }
    
    bool Pop_Queue(QueueList& Q,QElemType& e)
    {
        if(IsEmpty_Queue(Q))
            return false;
        QPtr p=Q.head->next;
        e=p->data;
        Q.head->next=p->next;
        if(p==Q.tail)//若头指针后面就是尾指针,需改动Q.tail的值
            Q.tail=Q.head;
        delete p;
        Q.length--;//bug2:忘记该行代码
        return true;
    }
    
    void LevelOrder_BiTree(BiTree T)//利用队列层序遍历
    {
        QueueList Q;
        Init_Queue(Q);
        Push_Queue(Q,T);
        while(!IsEmpty_Queue(Q)){
            BiTree bt;
            Pop_Queue(Q,bt);
            cout<<bt->data<<endl;
            if(bt->lchild)
                Push_Queue(Q,bt->lchild);
            if(bt->rchild)
                Push_Queue(Q,bt->rchild);
        }
    }
    //构造的栈为非递归 先序、中序、后序遍历服务
    #define SElemType BiTree
    typedef struct SNode
    {
        SElemType data;
        struct SNode* next,* prior;
    }SNode,* SLink;
    
    typedef struct
    {
        SLink head,tail;
        int length;
    }LinkStack;
    
    bool Init_Stack(LinkStack& S)
    {
        S.head=new SNode;
        if(!S.head)
            return false;
        S.head->next=S.head->prior=nullptr;
        S.tail=S.head;
        S.length=0;
        return true;
    }
    
    bool IsEmpty_Stack(LinkStack S)
    {
        if(!S.length)
            return true;
        return false;
    }
    SElemType GetTop_Stack(LinkStack S)
    {
        return S.tail->data;
    }
    
    bool Push_Stack(LinkStack& S,SElemType e)
    {
        SLink p=new SNode;
        if(!p)
            return false;
        p->data=e;
        p->next=S.tail->next;
        S.tail->next=p;
        p->prior=S.tail;
        S.tail=p;
        S.length++;
        return true;
    }
    
    bool Pop_Stack(LinkStack& S,SElemType& e)
    {
        SLink p=S.tail;
        e=S.tail->data;
        S.tail=S.tail->prior;
        S.tail->next=p->next;
        delete p;
        S.length--;
        return true;
    }
    
    void PreOrder_Bitree1(BiTree bt)//非递归先序遍历 使用栈
    {
        BiTree T=bt;
        LinkStack S;
        Init_Stack(S);
        while(T||!IsEmpty_Stack(S)){
            while(T){
                cout<<T->data<<endl;
                Push_Stack(S,T);
                T=T->lchild;
            }
            if(!IsEmpty_Stack(S)){
                Pop_Stack(S,T);
                T=T->rchild;
            }
        }
    }
    
    void InOrder_bitree1(BiTree bt)//非递归中序遍历 使用栈
    {
        BiTree T=bt;
        LinkStack S;
        Init_Stack(S);
        while(T||!IsEmpty_Stack(S)){
            while(T){//T一直向左遍历,并将沿途结点压入栈
                Push_Stack(S,T);
                T=T->lchild;
            }
            if(!IsEmpty_Stack(S)){//从栈中得到双亲
                Pop_Stack(S,T);
                cout<<T->data<<endl;//打印结点数据
                T=T->rchild;
            }
        }
    }
    
    void PostOrder_BiTree1(BiTree bt)//非递归后序遍历 使用栈
    {
        BiTree T=bt;
        LinkStack S;
        Init_Stack(S);
        while(T||!IsEmpty_Stack(S)){
            while(T){//T一直向左遍历,并将沿途结点压入栈
                T->flag=0;//在入栈之前将T->flag置为0,不然在main调用两次PostOrder_BiTree1,第二个会发生错误
                Push_Stack(S,T);
                T=T->lchild;
            }
            while(!IsEmpty_Stack(S)&&GetTop_Stack(S)->flag==1){
                Pop_Stack(S,T);
                cout<<T->data<<endl;//打印结点数据
            }
            if(!IsEmpty_Stack(S)){//若flag不为1,则不输出,然后继续向右子树遍历
                T=GetTop_Stack(S);
                T->flag=1;
                T=T->rchild;
            }
            else//左->右->根  当栈空时,遍历已经全部完成
                break;
        }
    }
    //以下的操作大多建立在遍历的基础之上 根据不同的要求进行不同的遍历
    BiTree Clear_BiTree(BiTree& T)//清空二叉链表(选择递归后序遍历,好处:左右子树操作完后,才进行根的删除)
    {
        BiTree bt=T;
        if(bt){
            bt->lchild=Clear_BiTree(bt->lchild);
            bt->rchild=Clear_BiTree(bt->rchild);
            delete bt;
            return nullptr;
        }
    }
    
    bool IsEmpty_BiTree(BiTree T)//二叉链表为空,返回true;否则返回false
    {
        if(!T)
            return true;
        return false;
    }
    
    int Depth_BiTree(BiTree T)//返回二叉树的深度(采用递归后序遍历,先找Max(H左,H右),然后将其+1
    {
        if(T){
            int Depth1=Depth_BiTree(T->lchild);
            int Depth2=Depth_BiTree(T->rchild);
            return (Depth1>Depth2?Depth1:Depth2)+1;
        }
        return 0;
    }
    
    BiTree Root(BiTree T)//返回指向根的指针
    {
        return T;
    }
    /*
    bool Value_BiTree(BiTree T,BiTree p)//输出p指向树结点的数据(这个三个次序都可以,在此我选择先序了)
    {
        BiTree bt=T;
        if(bt){
            if(p==bt){
                cout<<bt->data;
            }
            Value_BiTree(bt->lchild,p);
            Value_BiTree(bt->rchild,p);
        }
        return true;
    }
    */
    //291-304行代码  输出选择递归,若函数类型为返回,递归不太好完成,在此选择非递归先序
    TElemType Value_BiTree(BiTree T,BiTree p)
    {
        BiTree bt=T;
        LinkStack S;
        Init_Stack(S);
        while(bt||!IsEmpty_Stack(S)){//bug1: 将||写为&&
            while(bt){
                if(bt==p)
                   return bt->data;
                Push_Stack(S,bt);
                bt=bt->lchild;
            }
            if(!IsEmpty_Stack(S)){
                Pop_Stack(S,bt);//此处应为Pop_Stack(S,bt) 而不是Pop_Stack(S,e)
                bt=bt->rchild;
            }
        }
    }
    
    bool Assign_BiTree(BiTree& T,BiTree p,TElemType e)//将数据e赋给p指向树节点的数据域(递归先序遍历)
    {
        //BiTree bt=T;//递归不要这一行,非递归需要
        if(T){
            if(T==p){
                T->data=e;
            }
            Assign_BiTree(T->lchild,p,e);
            Assign_BiTree(T->rchild,p,e);
        }
        return true;
    }
    
    bool Assign_BiTree1(BiTree& T,BiTree p,TElemType e)//非递归先序遍历
    {
        BiTree bt=T;
        LinkStack S;
        Init_Stack(S);
        while(bt||!IsEmpty_Stack(S)){
            while(bt){
                if(p==bt){
                    bt->data=e;
                }
                Push_Stack(S,bt);
                bt=bt->lchild;
            }
            if(!IsEmpty_Stack(S)){
                Pop_Stack(S,bt);
                bt=bt->rchild;
            }
        }
        return true;
    }
    
    //输出 选择递归较容易,非输出 递归、非递归均可,看情况使用。若函数类型为返回,递归不太好完成,在此选择非递归先序
    void Parent_BiTree(BiTree T,BiTree p)//输出树指针p的双亲(选择递归先序遍历)   递归输出
    {
        if(T){
            if(T->lchild==p||T->rchild==p)
                cout<<T->data<<endl;
            Parent_BiTree(T->lchild,p);
            Parent_BiTree(T->rchild,p);
        }
    }
    
    BiTree Parent_BiTree1(BiTree T,BiTree p)//非递归返回  先序遍历
    {
        BiTree bt=T;
        LinkStack S;
        Init_Stack(S);
        if(T==p)//p为总根,无双亲
            return nullptr;
        while(bt||!IsEmpty_Stack(S)){
            while(bt){
                if(bt->lchild==p||bt->rchild==p)
                   return bt;
                Push_Stack(S,bt);
                bt=bt->lchild;
            }
            if(!IsEmpty_Stack(S)){
                Pop_Stack(S,bt);
                bt=bt->rchild;
            }
        }
        return nullptr;
    }
    //二叉链表找双亲、兄弟需要从头开始遍历 找孩子不需要遍历
    BiTree LeftChild_BiTree(BiTree T,BiTree p)//返回树指针p的左孩子,若无,返回nullptr
    {
        return p->lchild;
    }
    
    BiTree RightChild_BiTree(BiTree T,BiTree p)//返回树指针p的右孩子,若无,返回nullptr
    {
        return p->rchild;
    }
    
    BiTree LeftSibling(BiTree T,BiTree p)//返回树指针p的左兄弟指针,若无,返回nullptr
    {
        return Parent_BiTree1(T,p)->lchild;
    }
    
    BiTree RightSibling(BiTree T,BiTree p)//返回树指针p的右兄弟指针,若无,返回nullptr
    {
        return Parent_BiTree1(T,p)->rchild;
    }
    
    bool InsertChild_BiTree(BiTree& T,BiTree p,int LR,BiTree e)//LR=0:插入数据e到p指针的左孩子结点
                                                               //LR=1:插入数据e到p指针的右孩子结点
    {
        if(LR==0){
            if(!p->lchild){
                p->lchild=e;
                return true;
            }
            return false;
        }
        else{
            if(!p->rchild){
                p->rchild=e;
                return true;
            }
            return false;
        }
    }
    
    bool DeleteChild_BiTree(BiTree& T,BiTree p,int LR,BiTree e)//LR=0:删除p指针的子树(采用非递归后序遍历 ,最后删除根)
                                                               //LR=1:删除p指针的子树
    {
        BiTree bp=p;
        if(LR==0){
            bp=p->lchild;
            p->lchild=nullptr;
        }
        else{
            bp=p->rchild;
            p->rchild=nullptr;
        }
        LinkStack S;
        Init_Stack(S);
        while(bp&&!IsEmpty_Stack(S)){
            while(bp){
                bp->flag=0;//入栈前设置bp->flag=0
                Push_Stack(S,bp);
                bp=bp->lchild;
            }
            while(!IsEmpty_Stack(S)&&GetTop_Stack(S)->flag==1){
                Pop_Stack(S,bp);
                delete bp;
            }
            if(!IsEmpty_Stack(S)){
                bp=GetTop_Stack(S);
                bp->flag=1;
                bp=bp->rchild;
            }
            else
                break;
        }
        return true;
    }
    //while循环可以替代递归
    
    int main()
    {
        BiTree T;
        Creat_BiTree(T);
        cout<<"非递归后序遍历\n";
        PostOrder_BiTree1(T);//非递归 记得将flag 重置为0
    
        /*T=Clear_BiTree(T);
        cout<<"非递归后序遍历\n";//Clear_BiTree的测试代码
        PostOrder_BiTree1(T);*/
    
        /*cout<<"深度:"<<Depth_BiTree(T)<<endl;
        cout<<"非递归后序遍历\n";
        PostOrder_BiTree1(T);
        cout<<"值:"<<Value_BiTree(T,T->lchild->rchild->lchild)<<endl;
        Assign_BiTree1(T,T->lchild->rchild,9.9);
        cout<<"非递归后序遍历\n";
        PostOrder_BiTree1(T);
        Assign_BiTree(T,T->lchild->rchild,11.1);
        cout<<"非递归后序遍历\n";
        PostOrder_BiTree1(T);*///Clear_BiTree Depth_BiTree  Assign_BiTree操作的测试代码
    
        /*cout<<"====="<<endl;
        Parent_BiTree(T,T->lchild->rchild);
        cout<<"====="<<endl;
        cout<<Parent_BiTree1(T,T->lchild->rchild->lchild)->data<<endl;
        cout<<"====="<<endl;
        cout<<LeftChild_BiTree(T,T->lchild->rchild)->data<<endl;
        cout<<"====="<<endl;
        cout<<RightChild_BiTree(T,T->lchild->rchild)<<endl;
        cout<<"===="<<endl;
        cout<<LeftSibling(T,T->lchild->rchild)->data<<endl;
        cout<<"===="<<endl;
        cout<<RightSibling(T,T->lchild)->data;*///Parent、LeftChild、RightChild、LeftSibling、RightSibling
                                                //操作的测试代码
        //下面为测试 InsertChild、deleteChild操作的代码
        BiTree T2;
        Creat_BiTree(T2);
        cout<<"非递归后序遍历\n";
        PostOrder_BiTree1(T2);
        InsertChild_BiTree(T,T->lchild->lchild,0,T2);
        cout<<"非递归后序遍历\n";
        PostOrder_BiTree1(T);
        DeleteChild_BiTree(T,T->lchild->lchild,0,T2);
        cout<<"非递归后序遍历\n";
        PostOrder_BiTree1(T);
        return 0;
    }
    
    

    main函数的测试图如下所示
    在这里插入图片描述

    1.1
    2.2
    4.4
    @
    6.6
    @
    @
    5.5
    7.7
    @
    @
    @
    3.3
    @
    @
    非递归后序遍历
    6.6
    4.4
    7.7
    5.5
    2.2
    3.3
    1.1
    8.8
    9.9
    @
    11.1
    @
    @
    12.2
    @
    13.3
    @
    @
    非递归后序遍历
    11.1
    9.9
    13.3
    12.2
    8.8
    非递归后序遍历
    11.1
    9.9
    13.3
    12.2
    8.8
    6.6
    4.4
    7.7
    5.5
    2.2
    3.3
    1.1
    非递归后序遍历
    6.6
    4.4
    7.7
    5.5
    2.2
    3.3
    1.1
    
    Process returned 0 (0x0)   execution time : 16.433 s
    Press any key to continue.
    
    
    展开全文
  • 算法 非递归后序遍历二叉树总结(2种方法) @author:Jingdai @date:2020.12.04 传送门 非递归先序遍历二叉树 非递归中序遍历二叉树 方法1 非递归用栈来辅助遍历,后序遍历是第三次遇到该节点再遍历,但是栈只能...

    算法 非递归后序遍历二叉树总结(2种方法)

    @author:Jingdai
    @date:2020.12.04

    传送门

    方法1

    非递归用栈来辅助遍历,后序遍历是第三次遇到该节点再遍历,但是栈只能给我们提供遇到两次的判断方法,第一次是入栈时,第二次是出栈时,它们分别对应着二叉树的先序和中序遍历。所以我们需要利用一些技巧来辅助我们判断,这也是后序遍历二叉树比先序和中序稍微复杂一点的原因。

    看着代码进行分析。

    public static void postOrderTraverse(TreeNode root) {
    
        TreeNode p = root;
        TreeNode pre = null;
        LinkedList<TreeNode> stack = new LinkedList<>();
    
        while (p != null || stack.size() != 0) {
            while (p != null) {
                stack.push(p);
                p = p.left;
            }
            p = stack.pop();
            if (p.right == null) { // leaf 
                pre = p;
                System.out.println(p.val);
                p = p.right;
            } else if (p.right == pre) { // pre is p.right
                pre = p;
                System.out.println(p.val);
                p = null;
            } else {  // p.right dont traverse
                stack.push(p);
                p = p.right;
            }
        }
    }
    

    过程和前序中序基本一样,那什么时候我们需要遍历呢?当这个节点是叶子节点时或当这个节点的右子树已经遍历完了时就可以遍历了,否则我们再次将它入栈,等待下次遍历。同时也说明只有当这个节点是叶子节点或者这个节点的右子树已经访问完了时这个节点才能顺利出栈。

    • 叶子节点判断

      叶子节点很好判断,只要它的右孩子为 null 就代表它是叶子节点,因为左孩子一定为 null,否则不会从前面那个 while 中跳出。

    • 右子树是否遍历完判断

      看上面代码,我们是在顺利出栈的时候进行遍历,而后序遍历当前节点的上一个遍历节点就是它的右孩子,我们用 pre 记录上次顺利出栈的节点,判断如果当前节点的右子节点就是上一个顺利出栈的节点,代表右子树已经遍历完了,就遍历当前节点。

    接下来还有一个问题,前序和中序遍历时,在弹出一个节点时都是直接让 p = p.right ,接着去访问右子树,后序遍历有点不同。第一次弹出这个节点时,和前序和中序一样,需要接着去访问其右子树,使 p = p.right ;但是当第二次弹出这个节点时,即上面判断它的右子树已经访问完了时,就不能再去访问右子树了,要不就会死循环了,应该让 p = null,继续出栈元素。

    懂了上面上面代码后,发现其实上面两个分支可以合成一个,所以最后的代码如下。

    public static void postOrderTraverse(TreeNode root) {
            
        TreeNode p = root;
        TreeNode pre = null;
        LinkedList<TreeNode> stack = new LinkedList<>();
    
        while (p != null || stack.size() != 0) {
            while (p != null) {
                stack.push(p);
                p = p.left;
            }
            p = stack.pop();
            // left or pre is p.right
            if (p.right == null || p.right == pre) { 
                pre = p;
                System.out.println(p.val);
                p = null;
            } else {  // p.right dont traverse
                stack.push(p);
                p = p.right;
            }
        }
    }
    

    方法2 Morris方法

    Morris方法和前序中序一样,只是它的遍历点不一样,它是在每个节点第二次访问时将它的左树的最右序列反着遍历一遍。但是这样会导致整个树的最右序列没有遍历,所以最后还要加一个整个树的最右序列遍历。这应该是最麻烦的二叉树遍历方法了。代码如下。

    public static void postOrderTraverse(TreeNode root) {
    
        TreeNode cur = root;
        TreeNode rightmost = null;
    
        while (cur != null) {
            if (cur.left != null) {
                rightmost = cur.left;
                while (rightmost.right != null && rightmost.right != cur) {
                    rightmost = rightmost.right;
                }
                if (rightmost.right == null) {
                    rightmost.right = cur;
                    cur = cur.left;
                } else {
                    rightmost.right = null;
                    reverseTraverse(cur.left);
                    cur = cur.right;
                }
            } else {
                cur = cur.right;
            }
        }
        reverseTraverse(root);
    }
    
    public static void reverseTraverse(TreeNode node) {
        TreeNode head = reverse(node);
        TreeNode p = head;
        while (p != null) {
            System.out.println(p.val);
            p = p.right;
        }
        reverse(head);
    }
    
    public static TreeNode reverse(TreeNode node) {
        if (node == null || node.right == null) {
            return node;
        }
    
        TreeNode cur = node;
        TreeNode next = node.right;
        TreeNode temp = node.right;
        cur.right = null;
        while (next != null) {
            temp = next.right;
            next.right = cur;
            cur = next;
            next = temp;
        }
        return cur;
    }
    
    展开全文
  • 今天小编就为大家分享一篇关于Java语言实现非递归实现的前中后序遍历总结,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
  • 本文主要分为两个部分:包括二叉树的构造和非递归后序遍历,都比较有参考价值,这里将思路整理出来。 第一个部分主要是通过先序和中序构造二叉树,参考文章为...

    本文主要分为两个部分:包括二叉树的构造和非递归后序遍历,都比较有参考价值,这里将思路整理出来。
    第一个部分主要是通过先序和中序构造二叉树,参考文章为https://blog.csdn.net/qq_35733751/article/details/80970664我觉得他的构造方式比较通用而且简洁,其实还有通过递归构造的方式我觉得比较麻烦,就没有采用。下为原理图:
    原理图
    主要思想:1.找到pre数组中先序序列中的根节点并创建树的根节点;2.通过匹配in数组中中序序列中的根节点,找到先序和中序中分割点位置;3.分别递归构建左子树和右子树。

    bitnode *createbt1(char*pre,char*in,int n){
    	if(n<=0){
    		return NULL;
    	}
    	if(pre==NULL||in==NULL){
    		return NULL;
    	}
    	
    	int k;
    	bitnode *s=NULL;
    	char*p=NULL;
    	
    	s=(bitnode*)malloc(sizeof(bitnode));
    	s->data=*pre;
    	
    	for(p=in;p<in+n;p++)
    	  if(*p==*pre)
    	   break;
    	k=p-in;
    	
    	s->lchild = createbt1(pre+1,in,k);
        s->rchild = createbt1(pre+k+1,p+1,n-k-1);
        return s;
    }
    

    第二部分为非递归遍历二叉树,访问序列为左-右-中,主要思想:1.将左孩子节点全部入栈;2.如果栈不为空且右孩子节点已被访问,出栈并访问该节点;3.找到栈顶元素遍历其右子树;4.循环上述过程直到栈为空;这里需要设置flag标记以访问过的变量,左孩子若被访问过标记0,右孩子若被访问过标记1。这里参考了:https://www.cnblogs.com/hicjiajia/archive/2010/08/27/1810055.html有兴趣可以进去看看。

    void postorder(bitree T){
        bitree p;
    	p=T;   
    	stack s;
    	inistack(s);
    	int flag[50];
    	while(p||!isempty(s)){
    		while(p){
    			push(s,p);
    			flag[s.top]=0;
    			p=p->lchild; 
    		}
    		while(!isempty(s)&&flag[s.top]==1){
    		    pop(s,p);
    			visit(p);
    		}
            if(!isempty(s)){
            	flag[s.top]=1;
            	p=gettop(s);
            	p=p->rchild;
    		}
    		else break;
    	}
    }
    

    以下附上完整代码,通过了Dev c++调试了:

    #include <stdio.h>
    #include <stdlib.h>
    #define elemtype int 
    typedef struct BiTNode{
    	elemtype data;
    	struct BiTNode *lchild,*rchild; 
    }bitnode,*bitree;
    //*********************创建二叉树************************
    bitnode *createbt1(char*pre,char*in,int n){
    	if(n<=0){
    		return NULL;
    	}
    	if(pre==NULL||in==NULL){
    		return NULL;
    	}
    	
    	int k;
    	bitnode *s=NULL;
    	char*p=NULL;
    	
    	s=(bitnode*)malloc(sizeof(bitnode));
    	s->data=*pre;
    	
    	for(p=in;p<in+n;p++)
    	  if(*p==*pre)
    	   break;
    	k=p-in;
    	
    	s->lchild = createbt1(pre+1,in,k);
        s->rchild = createbt1(pre+k+1,p+1,n-k-1);
        return s;
    }
    
    //*********************非递归后序遍历二叉树************************
    
    typedef struct {
    	bitree data[50];
    	int top;
    }stack;
    
    void inistack(stack &s){
    	s.top=-1;
    }
    
    void push(stack &s,bitree p){
        if(s.top==49) return;
    	s.data[++s.top]=p;
    }
    
    void pop(stack &s,bitree &p){
    	if(s.top==-1) return;
    	p=s.data[s.top--];
    } 
    
    void visit(bitree p){
    	printf("%c\n",p->data);
    }
    
    bool isempty(stack s){
    	if(s.top==-1){
    		return 1;
    	}else
    	    return 0;
    }
    
    bitree gettop(stack s){
       if(s.top==-1)
         return false;
       bitree p;  
       p=s.data[s.top];
       return p;	
    }
    
    void postorder(bitree T){
        bitree p;
    	p=T;   
    	stack s;
    	inistack(s);
    	int flag[50];
    	while(p||!isempty(s)){
    		while(p){
    			push(s,p);
    			flag[s.top]=0;
    			p=p->lchild; 
    		}
    		while(!isempty(s)&&flag[s.top]==1){
    		    pop(s,p);
    			visit(p);
    		}
            if(!isempty(s)){
            	flag[s.top]=1;
            	p=gettop(s);
            	p=p->rchild;
    		}
    		else break;
    	}
    }
    
    int main(){
      char pre[]={'a','b','d','g','c','e','f'};
      char in[]={'d','g','b','a','e','c','f'};
      bitree s=createbt1(pre,in,7);
      postorder(s);
    }
    
    
    展开全文
  • 线索二叉树后序线索化,后序遍历输出 一.写码思路 我们要进行后序遍历的化,需要记录每个结点的 Parent 结点,我之前觉得可能不需要这个,直接用前驱就行了,但是后序遍历结点的前驱不一定是他的 Parent 结点。 ...
  • 和先序非递归类似。若节点非空,压入栈中,节点指向它的右子。空的话判断栈内是否还有元素,有的话判断它的左子树是否非空,空的话直接退栈。非空节点指向它的左子树再退栈。 代码: 为了省事建树...
  • 这份代码是纯C写的,设计到许多栈、指针的操作,可读性不高,于是现在通过这份博客对于非递归后序遍历二叉树进行一个总结回顾。以及完善当时的部分注释。文章链戳这里 正文 进入正题,关于遍历二叉树常用的方法...
  • 二叉树非递归后序遍历算法(C语言)

    千次阅读 2020-07-23 16:17:55
    二叉树非递归后序遍历算法(C语言) 二叉树后序遍历的规律:左右根 后序非递归遍历中,访问根(子根)结点有两种情况 ①:遍历完左子树,需要遍历右子,需要从栈中访问最顶上的根(子根)结点从而得到右子的指针。...
  • 我们可以发现二叉树的后序遍历=镜像二叉树的先序遍历的反向输出。于是需要: 1.得到镜像二叉树 2.非递归的先序遍历镜像二叉树 3.将节点的访问结果存储在栈中,利用先入后出的特点将输出结果的顺序反向 class Tree { ...
  • # 后序遍历 def postOrder(root): if not root: return [] p = root stack, res = [root, ], [] while stack: root = stack.pop() res.append(root.val) if root.left: stack.append(root.left) if root....
  • C++非递归后序遍历

    千次阅读 2018-05-30 23:59:21
    //非递归后序遍历 void Non_rec__traversal(Node root) { Node temp = root; stack <snode> S; //初始化栈 while (temp) { //寻找最左边的结点 snode a; a.p = temp; a.visited = 0; S.push(a); temp...
  • 本篇用一棵根节点为8的二叉搜索遍历 8、5、10、3、7、9、11 #include<stdio.h> #include<stdlib.h> #pragma warning(disable:4996) typedef struct Tree { int Data; struct Tree *Lc; struct ...
  • C++二叉树非递归后序遍历

    千次阅读 2018-05-20 16:55:00
    //非递归后序遍历 void Back(treenode *root) { stack <node> s; while (root != NULL || !s.empty()) { //根节点非空,栈非空 while (root != NULL) { node a; a.t = root; a.tag = 0; s.push(a)...
  • 1.镜像二叉树先序遍历结果...可以发现,镜像二叉树先序遍历的结果倒置过来,刚好是原二叉树的后序遍历结果,因此,可以利用如下代码实现一颗后序遍历: vector<int> postOrderNoRe(TreeNode* root){ } ...
  • 二叉树的非递归后序遍历: 前中后序三种遍历的非递归实现,都是使用了栈的思想,而后序遍历是其中最复杂的一种,因此只要掌握了它就很容易理解其他两种。 下面给出思路和代码实现 后序遍历: 思想:左子树、右子、...
  • 采取非递归方法输出这棵二叉树的后序遍历序列。 ##样例输入 ABC##DE#G##F### ##样例输出 CGEFDBA 代码实现之前,想一想后序遍历是否像先序和中序那样,只要将visit函数的位置改动即可。当然这样做是不行的在先序和...
  • 写完二叉树的非递归中序遍历,再写下后序遍历 节点与结构没有改变,相比中序,先序在将子元素压栈时不对双亲结点作出栈 //结点 class TreeNode { private: char name_; public: int State; TreeNode* leftNode; ...
  • 递归方法和层序遍历请看 递归前序遍历、递归中序遍历、递归后序遍历、层序遍历和判断一棵是否为完全二叉树 非递归前序遍历二叉树 第一种方法: 利用栈实现 1.设置 node = root 2.循环执行以下操作 如果 node != ...
  • 以先序扩展序列建立二叉树,并实现其非递归后序遍历 #include <stdio.h> #include <iostream> #include <stdlib.h> #include <string.h> #include <stack> using namespace std; //...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 31,770
精华内容 12,708
关键字:

树的非递归后序遍历