遞歸非遞歸方式實現二叉樹的遍歷以及應用


二叉樹的遞歸遍歷很好理解,話不多說,上代碼

一、二叉樹遞歸遍歷的實現

 
         

#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("\n");
printf("中序遞歸");
InOrderTravel(T);
printf("\n");
printf("后序遞歸");
TailOrderTravel(T);
printf("\n");
Prestacktravel(T);
printf("\n");
Instacktravel(T);
printf("\n");
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("遞歸前序遍歷\n");
	pre1(T);
	cout<<"\n非遞歸前序遍歷"<<endl;
	pre2(T); 
	cout<<"\n遞歸中序遍歷\n";
	In1(T);
	cout<<"\n非遞歸中序遍歷\n";
	In2(T); 
	cout<<"\n遞歸后序遍歷\n";
	Post1(T);
	cout<<"\n非遞歸后序遍歷\n";
	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("\n非遞歸前序"); 
//	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("\n非遞歸中序");
//	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("\n遞歸中序");
//	 In1(T); 
//	 In2(T);
//	  printf("\n遞歸后序");
//	 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<<"\n輸入前序"<<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很經典


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM