#include"stdio.h"
#include"stdlib.h"
#define leng sizeof(bitnode)
#define OK 1
#define OVERFLOW -1
#define ERROR 0
#define stack_init_size 100
#define MAXSIZE 110
#define term 7
typedef char telemtype;
typedef struct bitnode
   //二叉树的二叉链表存储表示
{
    telemtype data;
    struct bitnode *lchild,*rchild; //左右孩子指针
}bitnode,*bitree;
typedef struct{
    bitree base;
    bitree top;
    int stacksize;
}sqstack;
typedef struct{
    bitnode *base;
    int front;
    int rear;
}sqqueue;
char bitreenode[MAXSIZE];
int initstack(sqstack *s)
{
    s->base=(bitree)malloc(stack_init_size*leng);
    if(!s->base) exit (OVERFLOW);
    s->top=s->base;
    s->stacksize=stack_init_size;
    return OK;
}
int gettop(sqstack s,bitnode *e)
{
    if(s.top==s.base) return ERROR;
    *e=*(s.top-1);
    return OK;
}
int push(sqstack *s,bitnode *e)
{
    if (s->top-s->base>=s->stacksize)
    {
        s->base=(bitree)realloc(s->base,(MAXSIZE)*leng);
        if(!s->base) exit (OVERFLOW);
        s->top=s->base+s->stacksize;
        s->stacksize=MAXSIZE;
    }
    *s->top++=*e;
    return OK;
}
int pop(sqstack *s,bitree * e)
{
    if(s->top==s->base) return ERROR;
    *e=--s->top;
    return OK;
}
int stackempty(sqstack *s)
{
    if(s->top==s->base)
  return 1;
    return 0;
}
int initqueue(sqqueue *q)
{
    q->base=(bitnode *)malloc(MAXSIZE*leng);
    if(!q->base) exit(OVERFLOW);
    q->front=q->rear=0;
    return OK;
}
int enqueue(sqqueue *q,bitnode *e)
{
    if((q->rear+1)%MAXSIZE==q->front) return ERROR;
    q->base[q->rear]=*e;
    q->rear=(q->rear+1)%MAXSIZE;
    return OK;
}
int dequeue(sqqueue *q,bitree e)
{
    if(q->front==q->rear) return ERROR;
    *e=q->base[q->front];
    q->front=(q->front+1)%MAXSIZE;
    return OK;
}
int queueempty(sqqueue *q)
{
    if(q->front==q->rear) return 1;
    return 0;
}
int visit(telemtype e)
{
    printf("%c",e);
    return OK;
}
int creatbitree(bitree *t)
{
  
    static i=0;
    if(bitreenode[i]==' ') {*t=NULL; i++;}
  else
  {
      if(!(*t=(bitree)malloc(leng))) exit(OVERFLOW);
        
      (*t)->data=bitreenode[i];
      i++;
      creatbitree(&(*t)->lchild);//递归构造左子树 
      creatbitree(&(*t)->rchild); //递归构造右子树 
  }
  return OK;
}
int preordertraverse1(bitree t,int(*visit)(telemtype e)) //先序遍历的递归算法
{
    if(t)
    {
        if(visit((t)->data))
        //访问根结点
            if(preordertraverse1((t)->lchild,visit))
   
                if(preordertraverse1((t)->rchild,visit))
    return OK;
    
                return ERROR;
    }
    else return OK;
}
int preordertraverse2(bitree t,int(*visit)(telemtype e)) //先序遍历的非递归算法
{
    
    sqstack s;
    bitree p;
    initstack(&s);
    p=t;
    while (p||!stackempty(&s))
    {
        if(p){
            push(&s,p);
   //根指针进栈
            if(!visit(p->data)) return ERROR;
  
            p=p->lchild;
   //访问左孩子
        }
        else{
            pop(&s,&p);
            p=p->rchild;
  //访问右孩子
        }
    }
    return OK;
}
int inordertraverse1(bitree t,int(*visit)(telemtype e))
{
    if(t)
    {
        if(inordertraverse1(t->lchild,visit))
            if(visit(t->data))
                if(inordertraverse1(t->rchild,visit)) return OK;
                return ERROR;
    }
    else return OK;
}
int inordertraverse2(bitree t,int(*visit)(telemtype e))
{
    bitree p;
    sqstack s;
    initstack(&s);
    p=t;
    while(p||!stackempty(&s))
    {
        if(p) 
        {
            push(&s,p);
            p=p->lchild;/*向左走到尽头*/
        }
        else{
            pop(&s,&p);
            if(!visit(p->data)) return ERROR;
            p=p->rchild;
        }
    }
    return OK;
}
int postordertraverse(bitree t,int(*visit)(telemtype e))
{
    if(t)
    {
        if(postordertraverse(t->lchild,visit))
            if(postordertraverse(t->rchild,visit))
                if(visit(t->data)) return OK;
                return ERROR;
    }
    else return OK;
}
void levelordertraverse(bitree t,int(*visit)(telemtype e))
{
    sqqueue q;
    bitree a;
    a=(bitree)malloc(leng);
    if (t)
    {
    
        initqueue(&q);
        enqueue(&q,t);
        while(!queueempty(&q))
        {
            dequeue(&q,a);
            visit(a->data);
            if(a->lchild) enqueue(&q,a->lchild);
            if(a->rchild) enqueue(&q,a->rchild);
        }
    }
}
int bitreedegree1(bitree t,int* a,int * b,int* c)
{
    if(!t) return ERROR;
    if(t->lchild&&t->rchild) ++(*a);
    else if(t->lchild||t->rchild)
  ++(*b);
        else ++(*c);
        bitreedegree1(t->lchild,a,b,c);
        bitreedegree1(t->rchild,a,b,c);
    return OK;
}
int bitreedegree2(bitree t,int* a,int * b,int* c)
{
    
    bitree p=t;
    sqstack s;
    initstack(&s);
    while (p||!stackempty(&s))
    {
        if (p)
        {
            push(&s,p);
            if(p->lchild&&p->rchild) ++(*a);
            else if(p->lchild||p->rchild) ++(*b);
            else ++(*c);
            p=p->lchild;
        }
        else{
            pop(&s,&p);
            p=p->rchild;
        }
    }
    return OK;
}
int bitreedepth(bitree t)
{
    int i,j;
    if(!t) return 0;
    if(t->lchild) i=bitreedepth(t->lchild);
    else i=0;
    if(t->rchild) j=bitreedepth(t->rchild);
    else j=0;
    return (i>=j)?(i+1):(j+1);
}
void main()
{
    int a,k,two=0,one=0,zero=0,depth;
    bitree t;
    static char c[40];
    char *menu[]={//选择菜单
            "\n\n\t\t1:preorder traverse\n",
            "\t\t2:inorder traverse\n",
            "\t\t3:postorder traverse\n",
            "\t\t4:datas' degree \n",
            "\t\t5:levelorder traverse\n",
            "\t\t6:bitree' depth\n",
            "\t\t0:exit\n",
            "\n\tselect[0-6]:"
    };
    t= (bitree)malloc(sizeof(bitnode));
    t=NULL;
    printf("\nnow create a tree,please input a preorder bitree:");
    gets(bitreenode);
    creatbitree(&t);
        for(k=0;k<=term;k++)
            printf("%s",menu[k]);
        scanf("%d",&a);
    
            while(1){//循环
            switch(a)
            {
              case 1:printf("\nthis is the recursion arithmetic:\n");
                preordertraverse1(t,visit);
                printf("\nthis is not the recursion arithmetic:\n");
                   preordertraverse2(t,visit);
                   break;
              case 2:
    printf("\nthis is the recursion arithmetic:\n");
                  inordertraverse1(t,visit);
    
                  printf("\nthis is not the recursion arithmetic:\n");
                  inordertraverse2(t,visit);
                  break;
              case 3:
    printf("\nthis is the recursion arithmetic:\n");
                  postordertraverse(t,visit);break;
              case 4: 
    printf("this is the recursion arithmetic:\n");
                  bitreedegree1(t,&two,&one,&zero);
                  printf("number of degree 2:%d\n",two);
                  printf("number of degree 1:%d\n",one);
                  printf("number of degree 0:%d\n",zero);
                  two=0;one=0;zero=0;
                  printf("this is not the recursion arithmetic:\n");
                  bitreedegree2(t,&two,&one,&zero);
                  printf("number of degree 2:%d\n",two);
                  printf("number of degree 1:%d\n",one);
                  printf("number of degree 0:%d\n",zero);
                      break;
              case 5: levelordertraverse(t,visit);break;
              case 6: depth=bitreedepth(t);
                  printf("tree depth is:%d",depth);
                  break;
              case 0: exit(0) ;
              default:printf("\ninput the wrong choice,retry(0-7)");
            }
            printf("\ninput your choice(0-6):");
            scanf("%d",&a);
            }
}