二叉树的各类操作

#include<stdio.h>  
#include<stdlib.h>  
#include<stack>
#include<queue>

  
typedef char ElemType;  
//树结构  
typedef struct tree  
{  
    ElemType data;  
    struct tree * lchild;  
    struct tree * rchild;    
}TreeNode,*Tree;  



//创建一棵树,#号结束 先序遍历创建 
void CreateTree(Tree &T){
	char ch;
	scanf("%c",&ch);
	if(ch == '#'){
		T = NULL;
	}else{
		T = (Tree)malloc(sizeof(TreeNode));
		if(T==NULL) return;
		T->data = ch;
		CreateTree(T->lchild);
		CreateTree(T->rchild);
	}
}

//递归先序遍历
void PreOrder(Tree T){
	if(T==NULL) return ;
	printf("%c",T->data);
	PreOrder(T->lchild);
	PreOrder(T->rchild);
}

//非递归先序遍历 
/*void PreOrder1(Tree T){
	if(T==NULL) return;
	Tree p = T;
	stack<Tree> s;
	while(p!=NULL||!s.empty()){
		 while(p!=NULL){
		 	printf("%c",p->data);
		 	s.push(p);
		 	p = p->lchild;
		 }
		 if(!s.empty()){
		 	p = s.top();
		 	s.pop();
		 	p=p->rchild;
		 }
	}
}*/

 

//递归中序遍历
void InOrder(Tree T){
	if(T==NULL) return ;
	InOrder(T->lchild);
	printf("%c",T->data);
	InOrder(T->rchild);
} 


//非递归中序遍历
/*void inOrder(Tree T){
	if(T == NULL) return ;
	Tree p = T;
	stack<Tree> s;
	while(p!=NULL || !s.empty()){
		while(p!=NULL){
			s.push(p);
			p = p->lchild;
		}
		if(!s.empty()){
			p = s.top();
		    cout<<p->data<<endl;
		    s.pop();
		    p->rchild;
		}
	}
} */
//递归后序遍历
void PostOrder(Tree T){
	if(T==NULL)return ;
	PostOrder(T->lchild);
	PostOrder(T->rchild);
	printf("%c",T->data);
}

//第一种思路:对于任一结点P,将其入栈,然后沿其左子树一直往下搜索,直到搜索到没有左孩子的结点,
//此时该结点出现在栈顶,但是此时不能将其出栈并访问,因此其右孩子还为被访问。所以接下来按照相同的规则对其右子树进行相同的处理,当访问完其右孩子时,该结点又出现在栈顶,此时可以将其出栈并访问。这样就保证了正确的访问顺序。可以看出,在这个过程中,每个结点都两次出现在栈顶,只有在第二次出现在栈顶时,才能访问它。因此需要多设置一个变量标识该结点是否是第一次出现在栈顶。
//第二种思路:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P 存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
//非递归后序遍历
/*void PostOrder1(Tree T){
	if(T==NULL) return;
	stack<Tree> s;
	Tree p = T;//当前节点
	Tree last = NULL;//上一次访问的节点
	s.push(T);
	while(!s.empty()){
		p = s.top();
		if((p->lchild==NULL&&p->rchild==NULL)||(last!=NULL&&(last==p->lchild||last==p->rchild))){
			printf("%c",p->data);
			s.pop();
			last = p;
		}else{
			if(p->rchild!=NULL)
			s.push(p->rchild); 
			if(p->lchild!=NULL) 
			s.push(p->lchild);
		}	
	}
} */

//递归求树的深度
int depthtree(Tree T){
	int ldepth;
	int rdepth;
	if(T==NULL) return 0;
	ldepth = depthtree(T->lchild);
	rdepth = depthtree(T->rchild);
	return (ldepth>rdepth)?(ldepth+1):(rdepth+1);	
}

//递归求树的子节点个数
int childsum(Tree T){
	if(T==NULL) return 0;
	if(T->lchild==NULL&&T->rchild==NULL){
		return 1;
	}
	return childsum(T->lchild)+childsum(T->rchild);
}

//递归交换左右子女 
void exchangetree(Tree T){
	if(T==NULL) return ;
	Tree tmp;
	if(T->lchild!=NULL||T->rchild!=NULL){
		 tmp = T->lchild;
		 T->lchild = T->rchild;
		 T->rchild = tmp;
		 exchangetree(T->rchild);
		 exchangetree(T->lchild);
	}
}

//递归层次打印二叉树
void floorprint(Tree T){
	if(T==NULL) return ;
	printf("%c",T->data);
	if(T->lchild!=NULL)
	floorprint(T->lchild);
	if(T->rchild!=NULL)
	floorprint(T->rchild);
} 

int main()  
{  
    Tree T;
	int depth,childsums;  
    printf("\n按先序序列输入结点序列,'#'代表空:");  
    CreateTree(T);  
  	depth=depthtree(T);
  	childsums = childsum(T);
  	printf("深度为%d",depth);
  	printf("叶子节点的个数为%d",childsums);
    printf("\n非递归先序遍历的结果:");  

    //PreOrder1(T);  
    printf("\n递归先序遍历的结果:  ");  
    PreOrder(T);  
    
    printf("\n非递归中序遍历的结果:");  
    //InOrder1(T);  
    printf("\n递归中序遍历的结果:  ");  
	InOrder(T);  
  
    printf("\n非递归后序遍历的结果:");  
    //PostOrder1(T);  
    printf("\n递归后序遍历的结果:  ");  
    PostOrder(T);  
    printf("\n");  
  
}  
  

  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值