二叉树的遍历算法
二叉树
链式存储
二叉链表
typedef struct BTNode{
ElemType data;
struct BTNode *lchild, *rchild;
} BTNode, *BinTree;
三叉链表
typedef struct BTNode{
ElemType data;
struct BTNode *lchild, *rchild, *parent;
} BTNode, *BinTree;
二叉链表和三叉链表都是用来描绘二叉树的!!
二叉树的遍历
一、层序遍历
void LevelOrder(BinTree bt){
InitQueue(Q);//1.初始化队列
EnQueue(bt);//2.根结点入队
while(!QueueEmpty(Q)){//3.队列不为空
DeQueue(Q, p);//4.出队
if(p != NULL){//5.p结点不为空,则访问,并使孩子结点入队
visit(p->data);
EnQueue(p->lchild);
EnQueue(p->rchild);
}
}
}
//#define MaxSize 1024
void LevelQueue(BinTree bt){
const int MaxSize 1024;
BinTree q[MaxSize];
int front, rear;
front = rear = 0;
q[rear] = bt;
rear = (rear + 1) % MaxSize;
while(front != rear){
p = q[front];
front = (front + 1) % MaxSize;
if(p != NULL){
visit(p);
q[rear] = p->lchild;
rear = (rear + 1) % MaxSize;
q[rear] = p->rchild;
rear = (rear + 1) % MaxSize;
}
}
}
二、先序遍历
递归
void PreOrder(BinTree bt){
if(bt != NULL){//递归中止条件
visit(bt);
PreOrder(bt->lchild);
PreOrder(bt->rchild);
}
}
非递归
因为栈是后进先出,所以最后进去的栈是二叉树最近的根结点,第一次进入左子树需要进栈,第二次访问右子树的时候,则需要出栈。无论是访问左子树还是右子树,都需要找到其双亲结点才能访问,因此栈只是用来记录双亲结点的顺序。
void PreOrder(BinTree bt, VisitFunc visit){
InitStack(S);//1.初始化栈
p = bt;//2.p指向根结点
while(p != NULL || !StackEmpty(S)){//3.p不是空或者栈不空,则还有结点需要访问
if(p != NULL){//4.p不是空,则需要访问p结点,并且说明其左子树还未访问,第一次进入需要入栈
visit(p);
Push(S, p);
p = p->lchild;
}else{//5.p是空,说明其双亲结点必定访问过,需要出栈,访问栈顶元素的右子树(栈里面元素的右子树必然没有访问过)。
Pop(S, p);
p = p->rchild;
}
}
}
void PreOrder(BinTree bt){
InitStack(S);
Push(S, bt);
while(!StackEmpty(S)){
Pop(S, p);
if(p != NULL){
visit(p);
Push(S, p->rchild);//先进栈,后访问,所以右子树先进栈
Push(S, p->lchild);
}
}
}
三、中序遍历
递归
void InOrder(BinTree bt){
if(bt != NULL){
InOrder(bt->lchild);
visit(bt);
InOrder(bt->rchild);
}
}
非递归
void InOrder(BinTree bt){
InitStack(S);//1.初始化栈
BinNode *p = bt;//2.p指向根结点
while(p != NULL || !StackEmpty(S)){//3.p不为空,或者栈不为空,则还有结点需要访问
if(p){//4.p不为空,则第一次进过p,p进栈
Push(S, p);
p = p->lchild;
}else{//5.p是空,则栈顶元素是第二次经过,需要访问了,并且访问右结点
Pop(S, p);
visit(p);
p = p->rchild;
}
}
}
四、后续遍历
递归
void PostOrder(BinTree bt){
if(bt != NULL){
PostOrder(bt->lchild);
PostOrder(bt->rchild);
visit(bt);
}
}
非递归
void PostOrder(BinTree T){
InitStack(S);
InitStack(tag);//1.
p = T;//2.
while(p != NULL || !StackEmpty(S)){//3.
if(p != NULL){//4.
Push(S, p);
Push(tag, 1);
p = p->lchild;
}else{//5.
Pop(S, p);
Pop(tag, f);
if(f == 1){//6.
//从左子树返回,二次入栈,然后p转右子树
Push(S, p);
Push(tag, 2);
p = p->rchild;
}else{//7.
//从右子树返回(二次出栈),访问根结点,p转上层
visit(p);
p = NULL;//必须要,使下一步继续退栈
}
}
}
}