• 二叉树的非递归先序,中序,后序遍历


    #include<iostream> 
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<stack>
    using namespace std;
    
    struct Tree{
        int x;
        Tree *lchild, *rchild;
        Tree(){
            lchild = rchild = NULL;
        }
    };
    
    typedef Tree* pT;
    
    void buildT(pT &T){
        int n;
        cin>>n;
        if(n==-1)
            return;
        T = new Tree();
        T->x = n;
        buildT(T->lchild);
        buildT(T->rchild);
    }
    /**************************************************************************/ 
    /*
         非递归先序遍历: 对于任一结点P:
    
         1)访问结点P,并将结点P入栈;
    
         2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,
        循环至1); 若不为空,则将P的左孩子置为当前的结点P; 3)直到P为NULL并且栈为空,则遍历结束。
    */ void preOrderNorecursive(pT T){ stack<pT> s; s.push(T); while(!s.empty()){ while(T != NULL){//左子树走到尽头 cout<<T->x<<" "; T = T->lchild; s.push(T); } s.pop();//清除空指针 if(!s.empty()) { T = s.top(); s.pop(); s.push(T=T->rchild);//右子树走起 } } } void preOrderOutT(pT T){ if(T){ cout<<T->x<<" "; preOrderOutT(T->lchild); preOrderOutT(T->rchild); } } /**************************************************************************/ /* 非递归中序遍历:对于任一结点P, 1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理; 2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子; 3)直到P为NULL并且栈为空则遍历结束 */ void inOrderNorecursive(pT T){ stack<pT> s; s.push(T); while(!s.empty()){ while(T!=NULL)//左子树走到尽头 s.push(T=T->lchild); s.pop();//清除空指针 if(!s.empty()) { T = s.top(); s.pop(); cout<<T->x<<" "; s.push(T = T->rchild);//访问右子树 } } } void inOrderOutT(pT T){ if(T){ inOrderOutT(T->lchild); cout<<T->x<<" "; inOrderOutT(T->rchild); } } /**************************************************************************/ /* 非递归后序遍历: 要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。 如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子 都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈, 这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。 */ void postOrderNorecursive(pT T){ stack<pT> s; s.push(T); pT pre = NULL;//后序遍历之前输出的节点 while(!s.empty()){ T = s.top(); if(T->lchild==NULL && T->rchild==NULL || (pre!=NULL && (T->lchild==pre || T->rchild==pre)) { cout<<T->x<<" "; pre = T; s.pop(); } else {//依次将右子树和左子树放入栈中 if(T->rchild) s.push(T->rchild); if(T->lchild) s.push(T->lchild); } } } void postOrderOutT(pT T){ if(T){ postOrderOutT(T->lchild); postOrderOutT(T->rchild); cout<<T->x<<" "; } } /**************************************************************************/ int main(){ pT T = NULL; buildT(T); /**************************************************************************/ cout<<"递归先序遍历:"<<endl; preOrderOutT(T); cout<<endl; cout<<"非递归先序遍历:"<<endl; preOrderNorecursive(T); cout<<endl; /**************************************************************************/ cout<<"递归中序遍历:"<<endl; inOrderOutT(T); cout<<endl; cout<<"非递归中序遍历:"<<endl; inOrderNorecursive(T); cout<<endl; /**************************************************************************/ cout<<"递归后序遍历:"<<endl; postOrderOutT(T); cout<<endl; cout<<"非递归后序遍历:"<<endl; postOrderNorecursive(T); cout<<endl; /**************************************************************************/ return 0; }
    /*

    1 2 2 -1 -1 4 7 -1 -1 -1 3 4 -1 8 -1 -1 5 -1 -1
    递归先序遍历:
    1 2 2 4 7 3 4 8 5
    非递归先序遍历:
    1 2 2 4 7 3 4 8 5
    递归中序遍历:
    2 2 7 4 1 4 8 3 5
    非递归中序遍历:
    2 2 7 4 1 4 8 3 5
    递归后序遍历:
    2 7 4 2 8 4 5 3 1
    非递归后序遍历:
    2 7 4 2 8 4 5 3 1

    */
  • 相关阅读:
    根据现有文件生成图形化的目录树
    一个最简的短信验证码倒计时例子
    将指定目录下的所有资源整体迁移到另一个目录下
    通过 url 获取相应的 location 信息
    node-glob的*匹配
    mysql将查询出来的一列数据拼装成一个字符串
    Call to undefined function mysql_connect()错误原因
    JavaScript转unix时间戳
    .net3.0 中跨线程访问控件
    WPF的线程模型
  • 原文地址:https://www.cnblogs.com/hujunzheng/p/4694312.html
Copyright © 2020-2023  润新知