二叉树的遍历(前序+中序+后序)

来源:互联网 发布:最新在线报名系统源码 编辑:程序博客网 时间:2024/06/16 18:04
#include<stdio.h>#include<stdlib.h>#define OK 1#define ERROR 0 #define OVERFLOW -2 #define STACK_INIT_SIZE 100  //栈初始化分配量#define STACKINCREMENT 10    //存储空间的分配增量#define MAXQSIZE 20;typedef int Status ;//-------------二叉树的二叉链表----------------------typedef struct BiTNode{      char data;                  //数据域    struct BiTNode *lchild,*rchild;   //左右孩子指针  }BiTNode,*BiTree;  /*====================================================----------二叉树非递归遍历的辅助结构栈-----=====================================================*///前序非递归遍历和后序非递归遍历都是用栈作为辅助结构typedef struct {BiTree *base ;BiTree *top ;int stacksize ;}SqStack;//--------栈的初始化----------------------------Status InitStack(SqStack &S){S.base = (BiTree*)malloc(STACK_INIT_SIZE*sizeof(BiTree));if(!S.base) exit(OVERFLOW);S.top = S.base ;S.stacksize = STACK_INIT_SIZE;return OK ;}Status Push(SqStack &S ,BiTree P){//首先判断栈是否已满if((S.top-S.base) >= S.stacksize){S.base = (BiTree*)realloc(S.base,(STACK_INIT_SIZE+STACKINCREMENT)*sizeof(BiTree));if(!S.base) exit(OVERFLOW);S.top = S.base +S.stacksize ;S.stacksize +=STACKINCREMENT ;}*S.top = P ;S.top ++ ;return OK ;}BiTree Pop(SqStack &S){//判断栈是否已空if(S.base==S.top) return ERROR ;S.top = S.top-1 ;BiTree P = *S.top;return P ;}Status isEmpty(SqStack S){if(S.base==S.top)return OK ;return ERROR ;}BiTree GetTop(SqStack S){if(S.top==S.base) return NULL;return *(--S.top);}int StackLength(SqStack S){int length = 0;if(S.base==S.top) return 0 ;while(S.base!=S.top){length++ ;S.top-- ;}return length ;}/*===================队列=============================*/ typedef struct QNode {   BiTree data;   struct QNode *next; }QNode,*QueuePtr; typedef struct {   QueuePtr front,rear; /* 队头、队尾指针 */ }LinkQueue; Status InitQueue(LinkQueue *Q) { /* 构造一个空队列Q */   (*Q).front=(*Q).rear=(QueuePtr)malloc(sizeof(QNode));   if(!(*Q).front)     exit(OVERFLOW);   (*Q).front->next=NULL;   return OK; } Status DestroyQueue(LinkQueue *Q) { /* 销毁队列Q(无论空否均可) */   while((*Q).front)   {     (*Q).rear=(*Q).front->next;     free((*Q).front);     (*Q).front=(*Q).rear;   }   return OK; } Status ClearQueue(LinkQueue *Q) { /* 将Q清为空队列 */   QueuePtr p,q;   (*Q).rear=(*Q).front;   p=(*Q).front->next;   (*Q).front->next=NULL;   while(p)   {     q=p;     p=p->next;     free(q);   }   return OK; } Status QueueEmpty(LinkQueue Q) { /* 若Q为空队列,则返回TRUE,否则返回FALSE */   if(Q.front==Q.rear)     return true;   else     return false; } int QueueLength(LinkQueue Q) { /* 求队列的长度 */   int i=0;   QueuePtr p;   p=Q.front;   while(Q.rear!=p)   {     i++;     p=p->next;   }   return i; } Status GetHead_Q(LinkQueue Q,BiTNode *e) /* 避免与bo2-6.c重名 */ { /* 若队列不空,则用e返回Q的队头元素,并返回OK,否则返回ERROR */   QueuePtr p;   if(Q.front==Q.rear)     return ERROR;   p=Q.front->next;   *e=p->data;   return OK; } Status EnQueue(LinkQueue *Q,BiTNode e) { /* 插入元素e为Q的新的队尾元素 */   QueuePtr p=(QueuePtr)malloc(sizeof(QNode));   if(!p) /* 存储分配失败 */     exit(OVERFLOW);   p->data=e;   p->next=NULL;   (*Q).rear->next=p;   (*Q).rear=p;   return OK; } Status DeQueue(LinkQueue *Q,BiTNode *e) { /* 若队列不空,删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR */   QueuePtr p;   if((*Q).front==(*Q).rear)     return ERROR;   p=(*Q).front->next;   *e=p->data;   (*Q).front->next=p->next;   if((*Q).rear==p)     (*Q).rear=(*Q).front;   free(p);   return OK; } Status QueueTraverse(LinkQueue Q,void(*vi)(QElemType)) { /* 从队头到队尾依次对队列Q中每个元素调用函数vi()。一旦vi失败,则操作失败 */   QueuePtr p;   p=Q.front->next;   while(p)   {     vi(p->data);     p=p->next;   }   printf("\n");   return OK; }////////////////////////////////////////////////////////*====================================================           前序创建一个二叉链表=====================================================*///前序递归创建int CreateBiTree(BiTree &T){char data ;//按照次序输入二叉树中节点的值(一个字符),//'#'表示空树scanf("%c",&data);if(data=='#'){T=NULL ;}else{T = (BiTree) malloc(sizeof(BiTNode));if(!T) return -1 ;//生成根结点T->data = data ;//构造右子树CreateBiTree(T->lchild);//构造右子树CreateBiTree(T->rchild);}return 0 ;}//注意要想改成中序或是后序递归调用时:仅仅需改/*     //生成根结点 T->data = data ;//构造右子树CreateBiTree(T->lchild);//构造右子树CreateBiTree(T->rchild);*///的次序即可Status BiTreeEmpty(BiTree T){/*初始条件:树T存在. 操作结果:若树T为空则返回true,不空返回false*/if(T) return true;return false ;}char Root(BiTree T){if(!BiTreeEmpty(T))return NULL;elsereturn T->data;}char Value(BiTree p){/*树T存在,p是树中某个结点的指针,返回该指针的值*/return p->data;}void Assign(BiTree p,char value) { /* 给p所指结点赋值为value */   p->data=value; }/*====================================================二叉树的递归遍历(先,中,后)=====================================================*/void Visit(BiTree &T){if(T->data!='#'){printf("%c",T->data);}}void preOrder(BiTree &T){if(T==NULL) return ;Visit(T);preOrder(T->lchild);preOrder(T->rchild);return ;}void inOrder(BiTree &T){if(T==NULL) return ;inOrder(T->lchild);Visit(T);inOrder(T->rchild);return ;}void postOrder(BiTree &T){if(T==NULL)return ;postOrder(T->lchild);postOrder(T->rchild);Visit(T);}/*====================================================二叉树的非递归遍历(先,中,后)=====================================================*//*-----------      前序非递归遍历实现        -----------------*///二叉树的非递归前序遍历的思路:访问T->data后,将T入栈,遍历左子树;//遍历完左子树返回时,栈顶元素应为T,出栈,再先序遍历T的右子树。void preTraverse(BiTree T){BiTree P = T;        //工作指针(遍历指针)SqStack S ;          //工作栈,用来存放当前访问节点InitStack(S);//p不为空或栈不为空是循环while(P || !isEmpty(S)){if(P){// P  store stackPush(S,P);printf("%c",P->data);P=P->lchild ;}else{P=Pop(S);P= P->rchild;}}}//第二种实现方式void  preTraverse1(BiTree T){SqStack stack ;InitStack(stack);Push(stack , T);while(!isEmpty(stack)){BiTree P = Pop(stack);printf("%c",P->data);if(P->rchild!=NULL)Push(stack, P->rchild);if(P->lchild!=NULL)Push(stack,P->lchild);}}/*-----------      中序非递归遍历实现        -----------------*///主要思想:T是要遍历树的根指针,中序遍历要求在遍历完左子树后,访问根,再遍历右子树。//先将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,访问T->data,再中序遍历T的右子树。void InTraverse(BiTree T){BiTree P = T ;        //工作指针SqStack S ;          //工作栈,用来存放当前访问节点InitStack(S);        //初始化栈while(P || !isEmpty(S)){if(P){Push(S,P);P=P->lchild ;}else{P=Pop(S);printf("%c",P->data);P=P->rchild;}}}/*-----------      后序非递归遍历实现        -----------------*///visiting occurs only when current has no right child or last visited is his right child//后序非递归遍历是最难的一个遍历方式,但是我们可以从遍历的特点可以看出来,最先访问的节点最后遍历,因此符合栈的特点void PostTraverse(BiTree T){BiTree root = T ;SqStack S1,S2; //辅助栈,S1用来存储树入栈,S2用来存储后序遍历序列//初始化InitStack(S1); InitStack(S2) ;Push(S1,root);  //1.首先根节点入栈while(!isEmpty(S1)){ //当栈S1不为空时:1.先S1出栈 2.将从S1出栈的栈顶元素入栈S2BiTree P=Pop(S1);Push(S2,P);if(P->lchild !=NULL) Push(S1,P->lchild);if(P->rchild !=NULL) Push(S1,P->rchild) ;}while(!isEmpty(S2)){printf("%c",(*(--S2.top))->data);}}/*--------1.(先序)统计二叉树的叶子个数----------------*/int CountLeaf(BiTree T ,int &count){if(T){if((!T->lchild)&&(!T->rchild))count++ ;CountLeaf(T->lchild,count);CountLeaf(T->rchild,count);}return count ;}/*--------------2.(后序)二叉树的深度---------------*/int TreeHight(BiTree T){int height = 0;if(!T) return 0 ;else{int leftHeight = TreeHight(T->lchild);int rightHeight = TreeHight(T->rchild);return 1+(leftHeight>rightHeight?leftHeight:rightHeight);}}//按树状打印二叉树 void PrintTree(BiTree T,int nlayer){ if(T==NULL){  return    ;}   PrintTree(T->rchild,nlayer+1);  for(int i=0;i<nlayer;i++){   printf("  ");   }  printf("%c \n",T->data);    PrintTree(T->lchild,nlayer+1);  } /*--------------3.(后序)二叉树的复制---------------*/void main(){BiTree T ;if(BiTreeEmpty(T)){printf("Tree is NULL\n");}CreateBiTree(T);if(BiTreeEmpty(T)){printf("Tree is not NULL\n");}printf("root is =%c\n",Root(T));printf("c is parent =%c",Parent(T,'c'));/*++++++++++先序遍历++++++++++++*/printf("先序递归遍历如下\n");preOrder(T);printf("\n");printf("先序非递归遍历\n");preTraverse(T);printf("\n");printf("第二种方式的先序非递归\n");preTraverse1(T) ;printf("\n");/*+++++++中序遍历+++++++++*/printf("中序递归遍历如下\n");inOrder(T);printf("\n");printf("中序非遍历如下\n");InTraverse(T);printf("\n");/*++++++后序遍历+++++++++++++*/printf("后序递归遍历如下\n");postOrder(T);printf("\n");printf("后序非递归遍历如下\n");PostTraverse(T);printf("\n");/*++++++++++++++++++++++++++++*//*-----------应用-------------*/int count =0 ;CountLeaf(T,count) ;printf("二叉树的叶子个数为=%d\n",count);printf("二叉树的深度为:%d\n",TreeHight(T));int nlayer = 1 ;PrintTree(T,nlayer);}

0 0
原创粉丝点击