zoukankan      html  css  js  c++  java
  • 递归非递归方式实现二叉树的遍历以及应用

    二叉树的递归遍历很好理解,话不多说,上代码

    一、二叉树递归遍历的实现

    
    

    #include<iostream>
    #include <stdlib.h>
    #include<stack>
    #include<string.h>

    using namespace std;
    typedef struct TreeNode{
    TreeNode *right;
    TreeNode *left;
    char e;
    }TreeNode,*PTree;
    void CreatTree(PTree &T){
    char a;
    scanf("%c",&a);
    if(a=='#'){//ABDG##H###CE#I##F##
    T=NULL;
    }
    else{
    T = (PTree)malloc(sizeof(TreeNode));
    T->e=a;
    CreatTree(T->left);
    CreatTree(T->right);
    }
    }

    
    

    void PreOrderTravel(PTree T){
    if(T==NULL)
    return;
    printf("%c ",T->e);
    PreOrderTravel(T->left);
    PreOrderTravel(T->right);
    }
    void InOrderTravel(PTree T){
    if(T==NULL)
    return;
    InOrderTravel(T->left);
    printf("%c ",T->e);
    InOrderTravel(T->right);
    }
    void TailOrderTravel(PTree T){
    if(T==NULL)
    return;
    TailOrderTravel(T->left);
    TailOrderTravel(T->right);
    printf("%c ",T->e);
    }
    void Prestacktravel(PTree T){

    stack<TreeNode *> s;
    if(T!=NULL)
    s.push(T);
    printf("非递归前序 ");
    while(!s.empty()){
    PTree p=s.top();
    s.pop();
    printf("%c ",p->e);
    if(p->right!=NULL) s.push(p->right);
    if(p->left!=NULL) s.push(p->left);
    }
    }
    void Instacktravel(PTree T){
    stack<TreeNode *> s;
    PTree p=T;
    printf("非递归中序 ");
    while(!s.empty()||p!=NULL){
    if(p!=NULL){
    s.push(p);
    p=p->left;
    }else{
    p=s.top();
    s.pop();
    printf("%c ",p->e);
    p=p->right;
    }
    }
    }
    void Tailstacktravel(PTree T){
    stack<TreeNode *> s;
    PTree p=T,q=NULL;
    printf("非递归后序 ");
    do{
    while(p!=NULL){
    s.push(p);
    p=p->left;
    }
    q=NULL;
    while(!s.empty()){
    p=s.top();
    s.pop();
    if(p->right==q){
    printf("%c ",p->e);
    q=p;
    }else{
    s.push(p);
    p=p->right;
    break;
    }
    }
    }while(!s.empty());
    }

    
    


    int main(){
    PTree T=NULL;
    T = (PTree)malloc(sizeof(TreeNode));//此处不论是否为T申请内存都不影响最终结果,
    // 但是这点使我很疑惑,如果此处申请内存,在creaTree函数中继续申请内存,不是重复了吗?或者说是空置了一个
    //答:地址传递
    CreatTree(T);
    printf("前序递归");
    PreOrderTravel(T);
    printf(" ");
    printf("中序递归");
    InOrderTravel(T);
    printf(" ");
    printf("后序递归");
    TailOrderTravel(T);
    printf(" ");
    Prestacktravel(T);
    printf(" ");
    Instacktravel(T);
    printf(" ");
    Tailstacktravel(T);

    }

    
    

     

    在void InOrderTravel(PTree T)和T = (PTree)malloc(sizeof(TreeNode));中,T的类型都应该是PTree而非TreeNode,因为TreeNode是二叉树中每个结点,在参数传递时T表示的是当前根结点的指针。

    #include <stdlib.h>
    #include<stack>
    #include<string.h>
    #include<iostream>
    using namespace std;
    typedef struct Node{//ABDG##H###CE#I##F##
    	Node* left;
    	Node* right;
    	char data;
    }Node,*PNode;
    
    void create(PNode &T){
    	char c;
    	scanf("%c",&c);
    	if(c=='#') T=NULL;
    	else{
    		T=(PNode)malloc(sizeof(Node));//不要忘了申请地址
    		T->data=c;
    		create(T->left);
    		create(T->right);
    	}
    	
    }
    void pre1(PNode &T){
    	if(T) cout<<T->data<<" ";
    	if(T->left!=NULL) pre1(T->left);
    	if(T->right!=NULL) pre1(T->right); 
    }
    void pre2(PNode &T){
    	if(T==NULL) return;
    	stack<PNode>s;
    	PNode p=T;
    	while(!s.empty()||p){
    		while(p){
    			cout<<p->data<<" ";
    			s.push(p);
    			p=p->left; 
    		}
    		if(!s.empty()){
    			p=s.top();
    			s.pop();
    			p=p->right;
    		}
    	}
    }
    void In1(PNode &T){
    	if(T==NULL) return;
    	if(T->left!=NULL) In1(T->left);
    	cout<<T->data<<" ";
    	if(T->right!=NULL) In1(T->right);
    }
    void In2(PNode &T){
    	if(T==NULL) return;
    	PNode p=T;
    	stack<PNode>s;
    	while(p||!s.empty()){
    		while(p){
    			s.push(p);
    			p=p->left;
    		}
    		if(!s.empty()){
    			p=s.top();
    			s.pop();
    			cout<<p->data<<" ";
    			p=p->right;
    		}
    	}
    }
    void Post1(PNode &T){
    	if(T==NULL) return;
    	if(T->left!=NULL) Post1(T->left);
    	if(T->right!=NULL) Post1(T->right);
    	cout<<T->data<<" ";
    }
    void Post2(PNode &T){
    	stack<PNode>s;
    	PNode p=T,r=NULL;
    	while(p||!s.empty()){
    		if(p){
    			s.push(p);
    			p=p->left;
    		}else{
    			p=s.top();
    			if(p->right&&p->right!=r){
    				p=p->right;
    				s.push(p);
    				p=p->left;
    			}else{
    				s.pop();
    				cout<<p->data<<" ";
    				r=p;
    				p=NULL;
    			}
    		}
    	}
    } 
    void Post22(PNode &T){
    	 if (T == NULL)
            return;
        stack<PNode> s;
        //pCur:当前访问节点,pLastVisit:上次访问节点
        PNode pCur, pLastVisit;
    
        pCur = T;
        pLastVisit = NULL;
        //先把pCur移动到左子树最下边
        while (pCur)
        {
            s.push(pCur);
            pCur = pCur->left;
        }
        while (!s.empty())
        {
            //走到这里,pCur都是空,并已经遍历到左子树底端(看成扩充二叉树,则空,亦是某棵树的左孩子)
            pCur = s.top();
            s.pop();
            //一个根节点被访问的前提是:无右子树或右子树已被访问过
            if (pCur->right == NULL || pCur->right == pLastVisit)
            {
                cout <<pCur->data<<" ";
                //修改最近被访问的节点
                pLastVisit = pCur;
            }
            /*这里的else语句可换成带条件的else if:
            else if (pCur->lchild == pLastVisit)//若左子树刚被访问过,则需先进入右子树(根节点需再次入栈)
            因为:上面的条件没通过就一定是下面的条件满足。仔细想想!
            */
            else
            {
                //根节点再次入栈
                s.push(pCur);
                //进入右子树,且可肯定右子树一定不为空
                pCur = pCur->right;
                while (pCur)
                {
                    s.push(pCur);
                    pCur = pCur->left;
                }
            }
        }
        cout << endl;
    }
    int main(){
    	PNode T; 
    //	T=(PNode) malloc(sizeof(Node));
    	create(T);
    	printf("递归前序遍历
    ");
    	pre1(T);
    	cout<<"
    非递归前序遍历"<<endl;
    	pre2(T); 
    	cout<<"
    递归中序遍历
    ";
    	In1(T);
    	cout<<"
    非递归中序遍历
    ";
    	In2(T); 
    	cout<<"
    递归后序遍历
    ";
    	Post1(T);
    	cout<<"
    非递归后序遍历
    ";
    	Post2(T); 
    	return 0;
    } 
    
    
    ////https://blog.csdn.net/z_ryan/article/details/80854233
    //#include<iostream>
    //#include <stdlib.h>
    //#include<stack>
    //#include<string.h>
    //using namespace std;
    //typedef struct TreeNode{
    //	TreeNode *left,*right;
    //	char c;
    //}TreeNode,*pNode;
    //void create(pNode &T){
    //	char h;
    //	scanf("%c",&h);
    //	if(h=='#')
    //	T=NULL;
    //	else{
    //		T=(pNode)malloc (sizeof(TreeNode));
    //		T->c=h;
    //		create(T->left);
    //		create(T->right); 
    //	}
    //}
    //void pre1(pNode &T){
    //	
    //	printf("%c ",T->c);
    //	if(T->left!=NULL) pre1(T->left);
    //	if(T->right!=NULL) pre1(T->right);
    //}
    //void pre2(pNode &T){
    //	stack<pNode>s;
    //	printf("
    非递归前序"); 
    //	if(T!=NULL)
    //		s.push(T);
    //	while(!s.empty()){
    //		pNode p=s.top();
    //		s.pop();
    //		printf("%c ",p->c);	
    //	if(p->right!=NULL)	s.push(p->right);
    //	if(p->left!=NULL)	s.push(p->left);
    //	}
    //	
    //}
    //void In1(pNode &T){
    //	
    //	if(T->left!=NULL) In1(T->left);
    //	printf("%c ",T->c);
    //	if(T->right!=NULL) In1(T->right);
    //}
    //void In2(pNode &T){
    //	stack<pNode>s;
    //	printf("
    非递归中序");
    //	pNode p=T;
    //	while(p!=NULL||!s.empty()){
    //		if(p!=NULL){
    //			s.push(p);
    //			p=p->left;
    //		}else{
    //			p=s.top();
    //			s.pop();
    //			printf("%c ",p->c);
    //			p=p->right;
    //		}
    //	}
    //}
    //void Tail1(pNode &T){	
    //	if(T->left!=NULL) Tail1(T->left);
    //	if(T->right!=NULL) Tail1(T->right);
    //	printf("%c ",T->c);
    //}
    //int main(){
    //	TreeNode *T;//ABDG##H###CE#I##F##
    //	 T=(pNode)malloc(sizeof(TreeNode));
    //	 create(T);
    //	 printf("递归前序");
    //	 pre1(T);
    //	 pre2(T);
    //	 printf("
    递归中序");
    //	 In1(T); 
    //	 In2(T);
    //	  printf("
    递归后序");
    //	 Tail1(T); 
    //	return 0;
    //} 
    

      接下来是对二叉树进行应用

      求指定根节点的二叉树的节点数和深度,分别用了递归和非递归

    int Size1(PNode T){
    	if(T==NULL) return 0;
    	else return 1+Size1(T->left)+Size1(T->right); 
    }
    int Size2(PNode T){
    	if(T==NULL) return 0;
    	PNode p=T;
    	int i=0;
    	stack<PNode>s;
    	while(p||!s.empty()){
    		while(p){
    			i++;
    			s.push(p);
    			p=p->left;
    		}
    		if(!s.empty()){
    			p=s.top();
    			s.pop();
    			p=p->right;
    		}
    	}
    	return i;
    }
    int height2(PNode T){
    	if(T==NULL) return 0;
    	PNode p=T;
    	int i=0,max=0;
    	stack<PNode>s;
    	while(p||!s.empty()){
    		while(p){
    			i++;
    			if(i>max) max=i;
    			s.push(p);
    			p=p->left;
    		}
    		if(!s.empty()){
    			p=s.top();
    			s.pop();
    			i--;//出栈一个意味着深度减一
    			p=p->right;
    		}
    	}
    	return max;
    }
    int height1(PNode T){
    	if(T==NULL) return 0;
    	else{
    		int i=height1(T->left);
    		int j=height1(T->right);
    		return (i>j)?i+1:j+1;
    	}
    	
    }
    

      接下来是利用递归实现二叉树的前序中序转后序以及中序后序转前序

      

    //9
    //G H D B I E F C A
    //G D H B A E I C F
    //A B D G H C E I F
    //G D H B A E I C F
    
    #include <stdlib.h>
    #include<stack>
    #include<string>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef struct Node{
    	Node *right,*left;
    	char e;
    }Node,*PNode;
    const int maxn=30;
    char pre[maxn],in[maxn],post[maxn];
    int n;
    PNode CreatePre(int postl,int postr,int inl,int inr){
    	if(postl>postr)
    	return NULL;
    	PNode root=(PNode)malloc(sizeof(Node));
    	root->e=post[postr];
    	int k;
    	for(k=inl;k<=inr;k++){
    		if(in[k]==post[postr])
    		break;
    	}
    	int numLeft=k-inl; 
    	root->left=CreatePre(postl,postl+numLeft-1,inl,k-1);
    	root->right=CreatePre(postl+numLeft,postr-1,k+1,inr);
    	return root;
    }
    PNode CreatePost(int prel,int prer,int inl,int inr){
    	if(prel>prer) return NULL;
    	PNode root=(PNode)malloc(sizeof(Node));
    	root->e=pre[prel];
    	int k;
    	for(k=inl;k<=inr;k++){
    		if(in[k]==pre[prel])
    		break;	
    	}
    	int numleft=k-inl;
    	root->left=CreatePost(prel+1,prel+numleft,inl,inl+numleft-1);
    	root->right=CreatePost(prel+1+numleft,prer,inl+numleft+1,inr);
    	return root;
    }
    void pre1(PNode &T){
    	if(T) cout<<T->e<<" ";
    	if(T->left!=NULL) pre1(T->left);
    	if(T->right!=NULL) pre1(T->right); 
    }
    void Post1(PNode &T){
    	if(T==NULL) return;
    	if(T->left!=NULL) Post1(T->left);
    	if(T->right!=NULL) Post1(T->right);
    	cout<<T->e<<" ";
    }
    int main(){
    	cout<<"输入个数"<<endl; 
    	scanf("%d",&n);
    	cout<<"输入后序"<<endl; 
    	for(int i=0;i<n;i++)
    		cin>>post[i]; 
    	cout<<"输入中序"<<endl;
    	for(int i=0;i<n;i++)
    		cin>>in[i];
    	PNode root=CreatePre(0,n-1,0,n-1);
    	cout<<"构建后输出前序为"<<endl;
    	pre1(root);
    	cout<<"
    输入前序"<<endl; 
    	for(int i=0;i<n;i++)
    		cin>>pre[i]; 
    	cout<<"输入中序"<<endl;
    	for(int i=0;i<n;i++)
    		cin>>in[i];
    	PNode T=CreatePost(0,n-1,0,n-1);
    	cout<<"构建后输出后序为"<<endl;
    	Post1(T);
    	return 0;
    } 
    

      

     https://blog.csdn.net/z_ryan/article/details/80854233很经典

  • 相关阅读:
    hdu4587 Two Nodes 求图中删除两个结点剩余的连通分量的数量
    洛谷3388 tarjan割点
    POJ1523 Tarjan求割点以及删除割点之后强连通分量的数量
    POJ1144 tarjan+网络中割点与割边的数量
    POJ1780 欧拉路+手写栈解决爆战问题
    Delphi 窗体函数GetForegroundWindow
    Delphi 窗体函数GetClassName
    Delphi 窗体函数GetDesktopWindow
    Delphi 窗体函数 GetTopWindow、GetNextWindow
    Delphi 调用惯例 register, pascal, cdecl, stdcall, safecall 介绍
  • 原文地址:https://www.cnblogs.com/tao7/p/9488139.html
Copyright © 2011-2022 走看看