#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");
}
二叉树的各类操作
最新推荐文章于 2022-01-13 14:26:52 发布