1.二叉树的遍历
1.1先序遍历
若二叉树为空,则什么也不做;否则,
1)访问根结点
2)先序遍历左子树
3)先序遍历右子树
对应的递归算法如下:
void PreOrder(BiTree T){
if(T!=NULL){
visit(T); //访问根节点
PreOrder(T->lchild); //递归遍历左子树
PreOrder(T->rchild); //递归遍历右子树
}
}
非递归算法如下:
void PreOreder(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赋值为当前结点的右孩子
} //返回while循环继续进入if-else语句
}
}
1.2中序遍历
若二叉树为空,则什么也不做;否则,
1)中序遍历左子树
2)访问根结点
3)中序遍历右子树
对应的递归算法如下:
void InOrder(BiTree T){
if(T!=NULL){
InOrder(T->lchild); //递归遍历左子树
visit(T); //访问根节点
InOrder(T->rchild); //递归遍历右子树
}
}
非递归算法如下:
void InOreder(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); //栈顶元素出栈
visit(p); //访问出栈结点
p=p->rchild; //往右子树走,p赋值为当前结点的右孩子
} //返回while循环继续进入if-else语句
}
}
1.3后序遍历
若二叉树为空,则什么也不做;否则,
1)后序遍历左子树
2)后序遍历右子树
3)访问根结点
对应的递归算法如下:
void PostOrder(BiTree T){
if(T!=NULL){
PostOrder(T->lchild); //递归遍历左子树
PostOrder(T->rchild); //递归遍历右子树
visit(T); //访问根节点
}
}
非递归算法如下:
void PostOrder(BiTree T){
InitStack(S);
BiTNode *p=T;
BiTNode *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指针
}//每次出栈访问完一个结点就相当于遍历完所有以该结点为根的子树,需将p置NULL
}//else
}//while
}
1.4层次遍历
需要借助一个队列。首先将二叉树根结点入队,然后出队,访问出队结点;若它有左子树,则将左子树根结点入队,若它有右子树,则将右子树根结点入队。完成入队后出队,访问出队结点……如此反复,直至队列为空。
二叉树的层次遍历算法如下:
void LevelOrder(BiTree T){
InitQueue(Q); //初始化辅助队列
BiTree p;
EnQueue(Q,T); //将根结点入队
while(!IsEmpty(Q)){ //队列不空,循环继续
DeQueue(Q,p); //队头结点出队
vivit(p); //访问出队结点
if(p->lchild!=Null)
EnQueue(Q,p->lchild); //左子树不空,则将左子树根结点入队
if(p->rchild!=Null)
EnQueue(Q,p->rchild); //右子树不空,则将右子树根结点入队
}
}