二叉树的递归非递归的先序中序后序遍历以及层次遍历和求叶子节点数.docx
《二叉树的递归非递归的先序中序后序遍历以及层次遍历和求叶子节点数.docx》由会员分享,可在线阅读,更多相关《二叉树的递归非递归的先序中序后序遍历以及层次遍历和求叶子节点数.docx(16页珍藏版)》请在冰豆网上搜索。
![二叉树的递归非递归的先序中序后序遍历以及层次遍历和求叶子节点数.docx](https://file1.bdocx.com/fileroot1/2023-2/3/063240d7-1b68-4d44-8db6-33700ad9c8e8/063240d7-1b68-4d44-8db6-33700ad9c8e81.gif)
二叉树的递归非递归的先序中序后序遍历以及层次遍历和求叶子节点数
#include
#include
#include
#defineSTACK_INT_SIZE100//存储空间初始分配量
#defineSTACKINCREMENT10//存储空间分配增量
#defineOK1
#defineERROR0
#defineTRUE1
#defineFALSE0
#defineOVERFLOW-2
typedefcharTElemType;
typedefintStatus;
typedefcharSElemType;
//二叉树的二叉链表存储表示
typedefstructBiTNode
{
TElemTypedata;
structBiTNode*lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;
//用于存储二叉树结点的栈
typedefstruct
{
BiTree*base;
BiTree*top;
intstacksize;//当前已分配的存储空间
}SqStack;
//定义链式队列结点
typedefstructQNode
{
BiTreeQueuedata;
structQNode*next;
}QNode,*QueuePtr;
//定义链式队列
typedefstruct
{
QueuePtrfront;//
QueuePtrrear;
}LinkQueue;
//创建存储二叉树结点的空栈
StatusInitStack(SqStack&S)
{
S.base=(BiTree*)malloc(sizeof(BiTree));
if(!
S.base)exit(OVERFLOW);
S.top=S.base;
S.stacksize=STACK_INT_SIZE;
returnOK;
}
//存储二叉树结点的栈的取栈顶元素
StatusGetTop(SqStack&S,BiTree&e)
{
//若栈不空,则用e返回S的栈顶元素
if(S.top==S.base)returnERROR;
e=*(S.top-1);
returnOK;
}
//存储二叉树结点的栈的入栈操作
StatusPush(SqStack&S,BiTreee)
{
//插入元素e为栈顶元素
if(S.top-S.base>=S.stacksize)
{//若栈满,则追加存储空间
S.base=(BiTree*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(BiTree));
if(!
S.base)returnERROR;
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top=e;
S.top++;
returnOK;
}
//用于存储二叉树结点的栈出栈操作
StatusPop(SqStack&S,BiTree&e)
{
//删除S的栈顶元素,并用e返回
if(S.base==S.top)returnERROR;
S.top--;
e=*S.top;
returnOK;
}
//判断存储二叉树结点的栈是否为空
StatusStackEmpty(SqStackS)
{
//若栈S为空栈,则返回TRUE,否则返回FALSE
if(S.top==S.base)returnTRUE;
elsereturnFALSE;
}
//先序顺序创建一颗二叉树
StatusPreOrderCreateBiTree(BiTree&T)
{
//按先序次序输入二叉树中结点的值
//构造二叉链表表示的二叉树T
charch;
scanf("%c",&ch);
if(ch=='0')T=NULL;
else
{
//if(!
(T=(BiTree)malloc(sizeof(BiTree))))exit(OVERFLOW);//作用和下一语句的作用相同,注意两者的区别
if(!
(T=(BiTNode*)malloc(sizeof(BiTNode))))exit(OVERFLOW);
T->data=ch;//生成根结点
PreOrderCreateBiTree(T->lchild);//构造左子树
PreOrderCreateBiTree(T->rchild);//构造右子树
}
returnOK;
}//CreateBiTree
//递归先序遍历二叉树
voidPreOrder(BiTreebt)
{
if(bt)
{
printf("%c",bt->data);//先访问根节点
PreOrder(bt->lchild);//遍历左子树
PreOrder(bt->rchild);//遍历右子树
}
}
//递归中序遍历二叉树
voidInorder(BiTreebt)
{
if(bt)
{
Inorder(bt->lchild);//遍历左子树
printf("%c",bt->data);//访问根节点
Inorder(bt->rchild);//遍历右子树
}
}
//递归后序遍历二叉树
voidLastOrder(BiTreebt)
{
if(bt)
{
LastOrder(bt->lchild);//遍历左子树
LastOrder(bt->rchild);//遍历右子树
printf("%c",bt->data);//访问根节点
}
}
//非递归先序遍历二叉树方法一:
StatusPreOrderTraverse(BiTreeT)
{
SqStacks;
BiTreeP=T;
InitStack(s);
while(P!
=NULL||!
StackEmpty(s))
{
if(P!
=NULL)
{
printf("%c",P->data);
Push(s,P);//访问完之后将根节点入栈
P=P->lchild;
}
else
{
Pop(s,P);
P=P->rchild;
}
}
returnOK;
}
//非递归先序遍历二叉树方法二:
StatusPreOrderTraverse2(BiTreeT)
{
SqStacks;
BiTreeP=T;
InitStack(s);
Push(s,P);//先将根节点入栈
while(!
StackEmpty(s))
{
Pop(s,P);
if(P!
=NULL)
{
printf("%c",P->data);//访问根节点
Push(s,P->rchild);//先进栈,后访问,所以这里先让右子树进栈
Push(s,P->lchild);
}
}
returnOK;
}
//非递归中序遍历二叉树
StatusInOrderTraverse(BiTreeT)
{
//中序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit,也就是printf()函数
SqStackS;
InitStack(S);
BiTreep;
p=T;
/**/
while(p||!
StackEmpty(S))
{
if(p)
{
Push(S,p);
p=p->lchild;//根指针进栈,遍历左子树
}
else
{//根指针退栈,访问根结点,遍历右子树
Pop(S,p);
printf("%c",p->data);
p=p->rchild;
}
}//while
/*和上面的while开始的操作完全等同,可以视为方法二:
Push(S,p);
while(!
StackEmpty(S))
{
while(GetTop(S,p)&&p)
{
Push(S,p->lchild);
}
Pop(S,p);
if(!
StackEmpty(S))
{
Pop(S,p);
printf("%c",p->data);
Push(S,p->rchild);
}
}
*/
returnOK;
}//InOrderTraverse
/**/
//非递归后序遍历二叉树:
StatusLastOrderTraverse(BiTreeT)
{
//后序遍历时,分别从左子树和右子树共两次返回根结点,
//只有从右子树返回时才访问根结点,所以增加一个栈标记到达结点的次序。
SqStacks,tag;//定义两个栈,一个是存储二叉树结点的栈,一个是存储标志位的栈
//stack2tag;
BiTreef,m,n,P=T;//m,n是标志位。
f是中间变量,用于检测标志位是m还是n的
m=(BiTNode*)malloc(sizeof(BiTNode));//注意:
此处必须先创建结点,然后再赋值
m->data=1;
m->lchild=NULL;
m->rchild=NULL;
n=(BiTNode*)malloc(sizeof(BiTNode));//注意:
此处必须先创建结点,然后再赋值
n->data=2;
n->lchild=NULL;
n->rchild=NULL;
InitStack(s);//此栈用来存放结点
InitStack(tag);//此栈用来存放标志位,从左子树返回根节点时为1,从右子树返回根节点时为2
while(P||!
StackEmpty(s))
{
if(P)
{
Push(s,P);
Push(tag,m);//第一次入栈操作
P=P->lchild;
}
else
{
Pop(s,P);
Pop(tag,f);
if(f==m)
{
//从左子树返回,二次入栈,然后p转右子树
Push(s,P);
Push(tag,n);//第二次入栈
P=P->rchild;
}
else
{
//从右子树返回(二次出栈),访问根结点,p转上层
printf("%c",P->data);
P=NULL;//必须的,使下一步继续退栈
}
}
}
returnOK;
}
//初始化一个带头结点的队列
StatusInitQueue(LinkQueue&Q)
{
Q.front=(QNode*)malloc(sizeof(QNode));
if(!
Q.front)
exit(OVERFLOW);
Q.rear=Q.front;
Q.front->next=NULL;
returnOK;
}
//入队列
StatusEnQueue(LinkQueue&Q,BiTreee)
{
QueuePtrs=(QueuePtr)malloc(sizeof(QNode));
if(!
s)
exit(OVERFLOW);
s->Queuedata=e;
s->next=NULL;
Q.rear->next=s;
Q.rear=s;
returnOK;
}
//出队
intDelQueue(LinkQueue&Q,BiTree&e)
{
chardata1;
QueuePtrs;
s=Q.front->next;//注意:
该队列为带头结点,所以刚开始出队列时,应该去front的next
e=s->Queuedata;//获取对头记录的数据域,类型为BiTree
data1=e->data;//获取BiTree类型的数据域,类型为char
Q.front->next=s->next;
if(Q.rear==s)//队列中只有一个元素
Q.rear=Q.front;
free(s);
returnTRUE;
}
//队列的判断空操作
StatusQueueEmpty(LinkQueueQ)
{
//队列带头结点,所以需要判断Q.front->next
if(Q.front->next==NULL)
returnOK;
elsereturnERROR;
}
//按层次遍历
StatusHierarchyBiTree(BiTreebt)
{
LinkQueueQ;//保存当前节点的左右孩子的队列
InitQueue(Q);//初始化队列
BiTreep=bt;//临时保存树根Root到指针p中
if(bt==NULL)returnERROR;//树为空则返回
EnQueue(Q,p);//先将根节点入队列
while(!
QueueEmpty(Q))//若队列不空,则层序遍历
{DelQueue(Q,p);//出队列
printf("%C",p->data);//访问当前节点
if(p->lchild)
EnQueue(Q,p->lchild);//若存在左孩子,左孩子进队列
if(p->rchild)
EnQueue(Q,p->rchild);//若存在右孩子,右孩子进队列
}
//DelQueue(Q,p);//释放队列空间
returnOK;
}
//求叶子节点个数
intsum=0;//此处一定要定义为全局变量,因为递归调用退出函数的时候局部变量会销毁
intSumLefts(BiTreebt)
{
if(bt!
=NULL)
{
if(bt->lchild==NULL&&bt->rchild==NULL)
{
//printf("%4c",bt->data);
sum++;
}
sum=SumLefts(bt->lchild);
sum=SumLefts(bt->rchild);
}
return(sum);
}
voidmain()
{//注意创建二叉树时,用先序顺序创建
printf("请输入先序建立二叉树所需要的数据(例如ABD0000):
");
BiTreet;
PreOrderCreateBiTree(t);//利用先序顺序创建二叉树
printf("先序遍历输出为:
");
//PreOrder(t);//先序递归遍历
PreOrderTraverse(t);//先序非递归遍历
printf("\n");
printf("中序遍历输出为:
");
//InOrderTraverse(t);//中序非递归遍历
Inorder(t);//中序递归遍历
printf("\n");
printf("后序遍历输出为:
");
//LastOrder(t);//后序递归遍历
LastOrderTraverse(t);//后序非递归遍历
printf("\n");
printf("按层次遍历输出为:
");
HierarchyBiTree(t);//层次遍历,从上到下,从左到右
printf("\n");
printf("该二叉树中叶子节点个数为:
");
intleaves=SumLefts(t);
printf("%d",leaves);
printf("\n");
}