遍历二叉树(必背的七个算法)
遍历二叉树是以一定规则将二叉树中结点排列成一个线性序列,实质是对一个非线性结构进行线性化操作。
(1)前序遍历的递归实现
void PreOrder(BiTree bt)/*前序遍历二叉树bt*/
{ if (bt==NULL) return; /*递归调用的结束条件*/
Visit(bt->data); /*访问结点的数据域*/
PreOrder(bt->lchild); /*前序递归遍历bt的左子树*/
PreOrder(bt->rchild); /*前序递归遍历bt的右子树*/
}
(2)中序遍历的递归实现
void InOrder(BiTree bt) /*中序遍历二叉树bt*/
{ if (bt==NULL) return; /*递归调用的结束条件*/
InOrder(bt->lchild); /*中序递归遍历bt的左子树*/
Visit(bt->data); /*访问结点的数据域*/
InOrder(bt->rchild); /*中序递归遍历bt的右子树*/
}
(3)后序遍历的递归实现
void PostOrder(BiTree bt)/*后序遍历二叉树bt*/
{ if (bt==NULL) return; /*递归调用的结束条件*/
PostOrder(bt->lchild); /*后序递归遍历bt的左子树*/
PostOrder(bt->rchild); /*后序递归遍历bt的右子树*/ Visit(bt->data); /*访问结点的数据域*/
}
(4)层序遍历的实现
一维数组Queue[MAX_TREE_SIZE]用以实现队列,变量front和rear分别表示当前对队首元素和队尾元素在数组中的位置。
void LevelOrder(BiTree bt) /*层序遍历二叉树bt*/
{BiTree Queue[MAX_TREE_SIZE];
int front,rear;
if (bt==NULL) return;
front=-1;
rear=0;
queue[rear]=bt;
while(front!=rear)
{Visit(queue[++front]->data); /*访问队首结点数据域*/
if (queue[front]->lchild!=NULL) /*将队首结点的左孩子结点入队列*/
{ queue[++rear]=queue[front]->lchild;
}
if (queue[front]->rchild!=NULL) /*将队首结点的右孩子结点入队列*/
{queue[++rear]=queue[front]->rchild;
}
}
}
(5)前序遍历的非递归实现
二叉树以二叉链表存放,一维数组stack[MAX_TREE_SIZE]用以实现栈,变量top用来表示当前栈顶的位置。
void NRPreOrder(BiTree bt)/*非递归先序遍历二叉树*/
{ BiTree stack[MAX_TREE_SIZE],p;
int top;
if (bt==NULL) return;
top=0;
p=bt;
while(!(p==NULL&&top==0))
{ while(p!=NULL)
{ Visit(p->data); /*访问结点的数据域*/
if(top< MAX_TREE_SIZE-1)/*将当前指针p压栈*/
{stack[top++]=p;
}
else {printf(“栈溢出”);
return;
}
p=p->lchild; /*指针指向p的左孩子结点*/
}
if (top<=0) return; /*栈空时结束*/
else{ p=stack[- -top];/*从栈中弹出栈顶元素*/
p=p->rchild; /*指针指向p的右孩子结点*/
}
}
}
(6)中序遍历的非递归实现
只需将先序遍历的非递归算法中的Visit(p->data)移到p=stack[- -top]和p=p->rchild之间即可。
(7)后序遍历的非递归实现
后序遍历与先序遍历和中序遍历不同,在后序遍历过程中,结点在第一次出栈后,还需再次入栈,也就是说,结点要入两次栈,出两次栈,而访问结点是在第二次出栈时访问。因此,为了区别同一个结点指针的两次出栈,设置一标志flag,令:
flag=1 第一次出栈,结点不能访问 ; flag=2 第二次出栈,结点可以访问
当结点指针进、出栈时,其标志flag也同时进、出栈。因此,可将栈中元素的数据类型定义为指针和标志flag合并的结构体类型。定义如下:
typedef struct {
BiTree link;
int flag;
}stacktype;
后序遍历二叉树的非递归算法如下。在算法中,一维数组stack[MAX_TREE_SIZE]用于实现栈的结构,指针变量p指向当前要处理的结点,整型变量top用来表示当前栈顶的位置,整型变量sign为结点p的标志量。
void NRPostOrder(BiTree bt) /*非递归后序遍历二叉树bt*/
{ stacktype stack[MAX_TREE_SIZE];
BiTree p;
int top,sign;
if (bt==NULL) return;
top=-1; /*栈顶位置初始化*/
p=bt;
while (!(p==NULL && top==-1))
{ if (p!=NULL) /*结点第一次进栈*/
{ stack[++top].link=p;
stack[top].flag=1;
p=p->lchild; /*找该结点的左孩子*/
}
else{ p=stack[top].link;
sign=stack[top- -].flag;
if (sign==1) /*结点第二次进栈*/
{ stack[++top].link=p;
stack[top].flag=2; /*标记第二次出栈*/
p=p->rchild;
}
else { Visit(p->data); /*访问该结点数据域值*/
p=NULL;
}
}
}
}