zoukankan      html  css  js  c++  java
  • 二叉树的建立、销毁、各种遍历(递归、非递归)

    二叉树的基本操作,都使用递归:

    //二叉树   
    class Node  
    {  
    public:  
        char data;  
        Node *left;  
        Node *right;  
        Node():data(' '),left(NULL),right(NULL){}  
        Node(char ch):data(ch),left(NULL),right(NULL){}  
    };  
      
      
    //广义表建立二叉树,输入:A(B(D,E(G,)),C(,F))*   
    void CreateBinTree(Node* & Root,char *str)  
    {  
        stack<Node*> s;  
        Root=NULL;  
        Node* p=NULL,*t=NULL;  
        int k,i=0;  
        while(str[i])  
        {  
            switch(str[i])  
            {  
                case '(': s.push(p); k=1; break;  
                case ')': t=s.top(); s.pop(); break;  
                case ',': k=2; break;  
                default:  
                p=new Node(str[i]);  
                if(Root==NULL) Root=p;  
                else if(k==1)  
                {  
                    t=s.top(); t->left=p;  
                }  
                else  
                {  
                    t=s.top(); t->right=p;  
                }  
            }  
            ++i;  
        }  
    }  
      
    //递归先序遍历   
    void preOrderTraverse(Node *p)  
    {  
       if(p != NULL)  
       {  
           cout<<p->data;  
           preOrderTraverse(p->left);  
           preOrderTraverse(p->right);  
       }  
    }  
      
    //求节点个数   
    int Size(Node* root)  
    {  
        if(root == NULL) return 0;  
        return 1 + Size(root->left) + Size(root->right);  
    }  
      
    //求树的高度   
    int TreeDepth(Node* t)  
    {  
        int hl,hr,h;  
        if(t != NULL)  
        {  
            hl = TreeDepth(t->left);  
            hr = TreeDepth(t->right);  
            h = hl>hr? hl:hr;  
            return h+1;  
        }  
        return 0;  
    }  
      
    //销毁二叉树   
    void freeTree(Node*& p)  
    {  
        if(p->left != NULL)  
            freeTree(p->left);  
        if(p->right != NULL)  
            freeTree(p->right);  
        delete(p);  
    }  

    二叉树的各种遍历:

    //输出第level层的所有节点(从左到右),成功返回1   
    int PrintNodeAtLevel(Node* root,int level)  
    {  
        if(!root || level<0)  return 0;  
        if(level==0)  
        {  
            cout<<root->data<<" ";  
            return 1;  
        }  
        return PrintNodeAtLevel(root->left,level-1)+PrintNodeAtLevel(root->right,level-1);  
    }  
      
    //层次遍历二叉树,使用树的高度   
    void PrintNodeByLevel(Node* root,int depth)  
    {  
        for(int level=0; level<depth; level++)  
        {  
            PrintNodeAtLevel(root,level);  
            cout<<endl;  
        }  
    }  
    //层次遍历二叉树,不使用树的高度   
    void PrintNodeByLevel(Node* root)  
    {  
        for(int level=0; ;level++)  
        {  
            if(!PrintNodeAtLevel(root,level)) break;  
            cout<<endl;  
        }  
    }  
      
    /*层次遍历树算法: 
            (1)初始化队列为空 
            (2)若二叉树为空,直接返回 
            (3)将根节点指针放到队列中 
            (4)若队列非空,则重复以下操作: 
              1.队头元素出队并访问该元素 
              2.若该节点左孩子非空,则左孩子节点指针入队 
              3.若该节点右孩子非空,则右孩子节点指针入队 
    */  
    void layerOrder(Node* t)//层次遍历树   
    {  
        queue<Node*> q;  
        if(t==NULL) return;  
        q.push(t);  
        while(!q.empty())  
        {  
            Node* p=q.front();  
            q.pop();  
            cout<<p->data<<" ";  
            if(p->left) q.push(p->left);  
            if(p->right) q.push(p->right);  
        }  
    }  
      
    //层次遍历二叉树   
    void LevelOrder(Node* root)  
    {  
        if(root==NULL) return;  
        vector<Node*> v;  
        v.push_back(root);  
        int cur=0;  
        int last=1;  
        while(cur<v.size())  
        {  
            last=v.size();  
            while(cur<last)  
            {  
                cout<<v[cur]->data<<" ";  
                if(v[cur]->left) v.push_back(v[cur]->left);  
                if(v[cur]->right) v.push_back(v[cur]->right);  
                cur++;  
            }  
            cout<<endl;  
        }  
    }  
      
    //非递归先序遍历树   
    void preOrder(Node* root)  
    {  
        stack<Node*> s;  
        Node* p=NULL;  
        if(root==NULL) return;  
        s.push(root);  
        while(!s.empty())  
        {  
            p=s.top(); s.pop();  
            cout<<p->data<<" ";  
            if(p->right) s.push(p->right);  
            if(p->left) s.push(p->left);  
        }  
    }  
      
    //非递归先序遍历树   
    void preOrder(Node* t)  
    {  
        stack<Node*> s;  
        Node* p=t;  
        while (p!=NULL || !s.empty())  
        {  
            while (p!=NULL)  //遍历左子树   
             {  
                cout<<p->data<<" ";  
                s.push(p);  
                p=p->left;  
            }  
            if (!s.empty()) //通过下一次循环中的内嵌while实现右子树遍历   
             {  
                p=s.top();  
                s.pop();  
                p=p->right;  
            }  
         }  
    }  
      
    /*非递归中序遍历树算法:从根节点开始,只要当前节点存在,或者栈不为空,则重复下面操作: 
      (1)如果当前节点存在,则进栈并走左子树。 
      (2)否则退栈并访问,然后走右子树。 
    */  
    void inOrder(Node* t)  
    {  
        stack<Node*> s;  
        Node* p=t;  
        while(p||!s.empty())  
        {  
            if(p)  
            {  
                s.push(p);  
                p=p->left;  
            }  
            else  
            {  
                p=s.top();s.pop();  
                cout<<p->data<<" ";  
                p=p->right;  
            }  
        }  
    }  
      
    /*非递归后序遍历树:后序遍历,先遍历到的结点最后访问 
    用两个栈,一个栈用来遍历,另一个栈保存遍历到的结点,最后一起出栈,就是后序遍历结果 
    */  
    void postOrder(Node* root)  
    {  
        stack<Node*> sTraverse,sVisit;  
        Node* p=NULL;  
        if(root==NULL) return;  
        sTraverse.push(root);  
        while(!sTraverse.empty())  
        {  
            p=sTraverse.top(); sTraverse.pop();  
            sVisit.push(p);  
            if(p->left) sTraverse.push(p->left);  
            if(p->right) sTraverse.push(p->right);  
        }  
        while(!sVisit.empty())  
        {  
            p=sVisit.top(); sVisit.pop();  
            cout<<p->data<<" ";  
        }  
    }  
      
    /*非递归后序遍历树算法:从根节点开始,只要当前节点存在,或者栈不为空,则重复下面操作: 
      (1)从当前节点开始,进栈并走左子树,直到左子树为空。 
      (2)如果栈顶节点的右子树为空,或者栈顶节点的右孩子为刚访问过的节点, 
         则退栈并访问,然后置当前节点指针为空。 
      (3)否则走右子树。 
    */  
    void postOrder(Node* t)  
    {  
        Node *p,*q;  
        stack<Node*> s;  
        p=t;  
        q=NULL;  
        while(p!=NULL||!s.empty())  
        {  
            while(p!=NULL)  
            {  
                s.push(p); p=p->left;  
            }  
            if(!s.empty())  
            {  
                p=s.top();  
                if((p->right==NULL) || (p->right==q))  
                {  
                    cout<<p->data<<" ";  
                    q=p;  
                    s.pop();  
                    p=NULL;  
                }  
                else p=p->right;  
            }  
        }  
    }  
      
    /*根节点到r节点的路径: 
    后序遍历时访问到r节点时,栈中的所有的节点均为r节点的祖先,这些祖先构成根节点到r节点的路径 
    */  
    void nodePath(Node* root,Node* r)  
    {  
        Node *p,*q;  
        stack<Node*> s;  
        p=root;  
        q=NULL;   //q保存刚访问过的节点   
        while(p!=NULL||!s.empty())  
        {  
            while(p!=NULL)  
            {  
                s.push(p); p=p->left;  
            }  
            if(!s.empty())  
            {  
                p=s.top();  
                if( (p->right==NULL) || (p->right==q) )  
                {  
                    if(p==r)  
                    {  
                        while(!s.empty())  
                        {  
                            Node* t=s.top();  
                            s.pop();  
                            cout<<t->value<<" ";  
                        }  
                        return;  
                    }  
                    else  
                    {  
                        q=p;  
                        s.pop();  
                        p=NULL;  
                    }  
                }  
                else p=p->right;  
            }  
        }  
    }  
  • 相关阅读:
    Mongodb
    Java原子类
    volatile
    uniapp输入空格
    看不见的的html
    小程序隐藏scroll-view滚动条的方法
    云函数调用云函数 openid不存在
    vue路由中 Navigating to current location ("/xxx") is not allowed
    Vue: 单页面应用如何保持登录状态
    letter-spacing
  • 原文地址:https://www.cnblogs.com/luxiaoxun/p/2622775.html
Copyright © 2011-2022 走看看