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;  
            }  
        }  
    }  
  • 相关阅读:
    hadoop中namenode发生故障的处理方法
    开启虚拟机所报的错误:VMware Workstation cannot connect to the virtual machine. Make sure you have rights to run the program, access all directories the program uses, and access all directories for temporary fil
    Hbase的安装与部署(集群版)
    分别用反射、编程接口的方式创建DataFrame
    用Mapreduce求共同好友
    SparkSteaming中直连与receiver两种方式的区别
    privot函数使用
    Ajax无刷新显示
    使用ScriptManager服务器控件前后台数据交互
    数据库知识
  • 原文地址:https://www.cnblogs.com/luxiaoxun/p/2622775.html
Copyright © 2011-2022 走看看