递归遍历二叉树
先序遍历:
typedef struct BiTNode
{
Elemtype data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void PreOrder(BiTree T)
{
if(T!=NULL)
{
vist(T);//访问根节点
PreOrder(T->lchild);//递归遍历左子树
PreOrder(T->rchild);//递归遍历右子树
}
}
中序遍历
typedef struct BiTNode
{
Elemtype datal
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void InOrder(BiTree T)
{
if(T!=NULL)
{
I InOrder(T->lchild);//递归遍历左子树
vist(T);//访问根节点
InOrder(T->rchild);//递归遍历右子树
}
}
后序遍历
typedef struct BiTNode
{
Elemtype data;
struct BiTNode *lchild,*rchild;
}BiTNode,BiTree;
void PostOrder(BiTree T)
{
if(T!=NULL)
{
PostOrder(T->lchild);//递归遍历左子树
PostOrder(T->rchild);//递归遍历右子树
visit(T);//访问根节点
}
}
非递归遍历二叉树(需要使用栈)
中序遍历的访问流程:1⃣️沿着根的左孩子,依次将元素入栈,直到左孩子为空;2⃣️栈顶元素出栈并访问,并且判断它是否有右孩子,如果右孩子为空,继续执行2;如果有右孩子,转去执行1。
中序遍历的非递归算法如下:
typedef struct BiTNode
{
Elemtype data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void InOrder2(BiTree T)
{
InitStack(S);//初始化栈S
BiTree p=T;//p为遍历指针
while( p || !IsEmpty(S) )//p不空时或者栈不为空时循环
{
if(p)//一路向左
{
Push(S,p);//当前节点入栈
p=p->lchild;//左孩子不空,一直向左走
}
else//出栈,并转向出栈节点的右子树
{
Pop(S,p);//栈顶元素出栈,并将值存于p
vist(p);//访问出栈节点
p=p->rchild;//向右子树走,p赋值为当前节点的右孩子
}
}
}
先序遍历的访问流程:1⃣️先访问当前节点的元素,然后沿着当前节点的左孩子,将元素入栈,一直循环先访问再入栈,直到左孩子为空;2⃣️栈顶元素出栈,并且判断有没有右孩子,如果没有右孩子,继续栈顶元素出栈;如果有右孩子,继续执行1。
先序遍历的非递归算法如下:
typedef struct BiTNode
{
Elemtype data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void PreOrder2(BiTree T)
{
InitStack(S);//初始化栈S
BiTree p=T;//p是遍历指针
while( p || !IsEmpty(S) )//p不空时或者栈不空时循环
{
if(p)//一路向左
{
visit(p);//访问当前节点
Push(S,p);//当前节点入栈
p=p->lchild;//左孩子不为空,一直向左走
}
else//出栈,并转向出栈节点的右子树
{
Pop(S,p);//栈顶元素出栈
p=p->rchild;//向右子树走,p赋值为当前节点的右孩子
}
}
}
后序遍历的思路分析:1⃣️沿着根的左孩子,依次入栈,直到左孩子为空。2⃣️读栈顶元素:若其右孩子不空且未被访问过,将右子树转向执行1;否则,栈顶元素出栈并访问。
在2⃣️中必须分清返回时是从左子树还是返回的还是从右子树返回的,因此设定一个辅助指针r,用于指向最近访问过的节点。也可以在节点中增加一个标志域,记录是否已被访问。
typedef struct BiTNode
{
Elemtype data;
struct BiTNode *lchild,rchild;
}BiTNode,*BiTree;
void PostOrder2(BiTree T)
{
InitStack(S);
BiTree *p=T;
BiTree *r=NULL;
while( p || !IsEmpty(S) )
{
if(p)//走到最左边
{
push(S,p);
p=p->lchild;
}
else//向右
{
GetTop(S,p);//读栈顶节点(非出栈)
if(p->rchild && p->rchild!=r)//若右子树存在,且未被访问过
{
p=p->rchild;//转向右
}
else//否则弹出节点并访问
{
pop(S,p);//将节点弹出
visit(p->data);//访问该节点
r=p;//记录最近访问过的节点
p=NULL;//节点访问完后,重置p指针
}
}
}
}
二叉树的层次遍历:进行层次遍历需要借助一个队列。
层次遍历的思想如下:1⃣️首先将二叉树的根节点入队。2⃣️若队列非空,则队头节点出队,访问该节点,若它有左孩子,则将其左孩子入对;若它有右孩子,则将其右孩子入队。3⃣️重复2⃣️步,直至队列为空。
typedef struct BiTNode
{
ELemtype data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
void LevelOrder(BiTree T)
{
InitQueue(Q);//初始化辅助队列
BiTree p;
EnQueue(Q,T);//将根节点入队
while(!IsEmpty(Q))//队列不空则循环
{
Dequeue(Q,p);//队头节点出队
visit(p);//访问出队节点
if(p->lchild!=NULL)
{
EnQueue(Q,p->lchild);//若左孩子不空,则左孩子入队
}
if(p->rchild!=NULL)
{
EnQueue(Q,p->rchild);//若右孩子不空,则右孩子入队
}
}
}