DataStruture is the basis of programming,and then it is often mentioned during the interview to test how much a computer scientice graduate has mastered.Now I make a summary about it. ---------Noted by me
数据结构是程序设计的基础,面试时往往成为考核的重点,现总结归纳一下非递归遍历二叉树算法(包括前序、中序、后序):
#include<stdio.h>
#include<stdlib.h>
# define OK 1
# define OVERFLOW -1
# define ERROR 0
# define TRUE 1
# define FALSE 0
# define Maxsize 100
typedef char ElemType;
typedef struct BiTNode{//结点结构
ElemType data;//数据元素
struct BiTNode *lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;
typedef struct{
BiTree *base;
BiTree *top;
}SqStack;
void InitStack(SqStack &S){
//S.base=(BiTree*)malloc(20*sizeof(BiTree));
S.base=new BiTree[Maxsize];
if(!S.base)exit(-2);
S.top=S.base;
}
void Push(SqStack &S,BiTree p){
*S.top++=p;
}
void Pop(SqStack &S,BiTree &p){
p=*--S.top;
}
int StackEmpty(SqStack S){
if(S.top==S.base)return 1;
return 0;
}
BiTree GetTop(SqStack S){
return *(S.top-1);
}
void PreOrderTraverse(BiTree T){//先序遍历二叉树算法
if(T){
printf("%c",T->data);//访问结点
PreOrderTraverse(T->lchild);//遍历左子树
PreOrderTraverse(T->rchild);//遍历右子树
}
}
void InOrderTraverse(BiTree T){//中序遍历二叉树算法
if(T){
InOrderTraverse(T->lchild);//遍历左子树算法
printf("%c",T->data);//访问结点
InOrderTraverse(T->rchild);//遍历右子树
}
}
void PostOrderTraverse(BiTree T){//后序遍历二叉树算法
if(T){
PostOrderTraverse(T->lchild);//遍历左子树
PostOrderTraverse(T->rchild);//遍历右子树
printf("%c",T->data);//访问结点
}
}
int CreateBiTree(BiTree &T){
ElemType ch;
scanf("%c",&ch);
if(ch==' ')T=NULL;
else{
if(!(T=new BiTNode))exit(OVERFLOW);
T->data=ch;//生成根结点
CreateBiTree(T->lchild);//构造左子树
CreateBiTree(T->rchild);//构造右子树
}
return OK;
}//CreateBiTree
先序遍历的非递归算法:
(1)二叉树的根结点进栈。
(2)当栈不空循环:当栈顶元素非空时访问它,并将该结点的左子树的根结点进栈,直到栈顶元素为空,并将空指针出栈;如果栈不空,栈顶元素出栈,并将该结点的右子树的根结点进栈。如此操作,直到栈空为止。
void PreOrder_Nonrecursive(BiTree T){//先序遍历的非递归算法
SqStack S;
BiTree p;
InitStack(S);
Push(S,T);//根指针进栈
while(!StackEmpty(S)){
while(GetTop(S)){
printf("%c",GetTop(S)->data);//访问结点,向左一步
Push(S,GetTop(S)->lchild);
}//向左走到尽头
Pop(S,p);//空指针出栈
if(!StackEmpty(S)){//向右一步
Pop(S,p);
Push(S,p->rchild);
}
}//while
}//PreOrder_Nonrecursive
中序遍历的非递归算法:
(1)二叉树的根结点进栈。
(2)当栈不空循环:当栈顶元素非空时,将该结点的左子树的根结点进栈,直到栈顶元素为空,并将空指针出栈;如果栈不空,栈顶元素出栈,访问该元素,并将该结点的右子树的根结点进栈。如此操作,直到栈空为止。
void InOrder_Nonrecursive(BiTree T){//中序遍历的非递归算法
SqStack S;
BiTree p;
InitStack(S);
Push(S,T);//根指针进栈
while(!StackEmpty(S)){
while(GetTop(S))Push(S,GetTop(S)->lchild);//向左走到尽头
Pop(S,p);//空指针出栈
if(!StackEmpty(S)){//访问结点,向右一步
Pop(S,p);
printf("%c",p->data);
Push(S,p->rchild);
}//if
}//while
}//InOrder_Nonrecursive
void main(){
BiTree T;
CreateBiTree(T);
PreOrderTraverse(T);
printf("\n");
InOrderTraverse(T);
printf("\n");
PostOrderTraverse(T);
printf("\n");
PreOrder_Nonrecursive(T);
printf("\n");
InOrder_Nonrecursive(T);
printf("\n");
}
--------------------------------------------------------------------------------------------------------------------------------------------------
#include<stdio.h>
#include<stdlib.h>
# define OK 1
# define OVERFLOW -1
# define ERROR 0
# define TRUE 1
# define FALSE 0
# define Maxsize 100
typedef char ElemType;
typedef struct BiTNode{//结点结构
ElemType data;//数据元素
struct BiTNode *lchild,*rchild;//左右孩子指针
}BiTNode,*BiTree;
typedef struct PMType{
BiTree ptr;
int mark;//mark=0表示刚刚访问此结点,mark=1表示左子树处理结束返回,mark=2表示右子树处理结束返回。
}PMType;
typedef struct{
PMType *base;
PMType *top;
}SqStack;
void InitStack(SqStack &S){
//S.base=(BiTree*)malloc(20*sizeof(BiTree));
S.base=new PMType[Maxsize];
if(!S.base)exit(-2);
S.top=S.base;
}
void Push(SqStack &S,PMType p){
*S.top++=p;
}
void Pop(SqStack &S,PMType &p){
p=*--S.top;
}
int StackEmpty(SqStack S){
if(S.top==S.base)return 1;
return 0;
}
PMType GetTop(SqStack S){
return *(S.top-1);
}
void PreOrderTraverse(BiTree T){//先序遍历二叉树算法
if(T){
printf("%c",T->data);//访问结点
PreOrderTraverse(T->lchild);//遍历左子树
PreOrderTraverse(T->rchild);//遍历右子树
}
}
void InOrderTraverse(BiTree T){//中序遍历二叉树算法
if(T){
InOrderTraverse(T->lchild);//遍历左子树算法
printf("%c",T->data);//访问结点
InOrderTraverse(T->rchild);//遍历右子树
}
}
void PostOrderTraverse(BiTree T){//后序遍历二叉树算法
if(T){
PostOrderTraverse(T->lchild);//遍历左子树
PostOrderTraverse(T->rchild);//遍历右子树
printf("%c",T->data);//访问结点
}
}
int CreateBiTree(BiTree &T){
ElemType ch;
scanf("%c",&ch);
if(ch==' ')T=NULL;
else{
if(!(T=new BiTNode))exit(OVERFLOW);
T->data=ch;//生成根结点
CreateBiTree(T->lchild);//构造左子树
CreateBiTree(T->rchild);//构造右子树
}
return OK;
}//CreateBiTree
后序遍历的非递归算法:
与先序遍历和中序遍历的非递归情况有所不同,在后序遍历二叉树的过程中,对一个结点访问之前,要两次经过这个结点,第一次是由该结点找到其左子树,对其左子树进行遍历,遍历完成后,返回到该结点。第二次是由该结点找到其右子树,对其右子树进行遍历,遍历完成后,返回该结点,此时才能访问该结点。
所以,在后序遍历的非递归算法中,同样需要一个栈,而且为了区分某一个结点是第一次进栈还是第二次进栈,在栈结构中还得设置一个标志域来区分。其栈结点的定义如下:
typedef struct PMType{
BiTree ptr;
int mark;//mark=0表示刚刚访问此结点,mark=1表示左子树处理结束返回,mark=2表示右子树处理结束返回。
}PMType;
void PostOrder_Stack(BiTree T){//后序遍历的非递归算法
PMType a;
SqStack S;
InitStack(S);//S的元素为PMType类型
a.ptr=T;
a.mark=0;
Push(S,a);//根结点入栈
while(!StackEmpty(S)){
Pop(S,a);
switch(a.mark){
case 0:a.mark=1;Push(S,a);//修改mark域
if(a.ptr->lchild) {a.ptr=a.ptr->lchild;a.mark=0;Push(S,a);} //访问左子树
break;
case 1:a.mark=2;Push(S,a); //修改mark域
if(a.ptr->rchild) {a.ptr=a.ptr->rchild;a.mark=0;Push(S,a);}//访问右子树
break;
case 2:printf("%c",a.ptr->data); //访问结点,返回
break;
}
}//while
}//PostOrder_Stack
void main(){
BiTree T;
CreateBiTree(T);
PreOrderTraverse(T);
printf("\n");
InOrderTraverse(T);
printf("\n");
PostOrderTraverse(T);
printf("\n");
PostOrder_Stack(T);
printf("\n");
}