#include <stdio.h>
#include <stdlib.h>
#define OK 1
typedef int Status;	
typedef struct BiTNode
{
	char data;   //结点数据域 
	struct BiTNode *lchild, *rchild;  //左右孩子指针 
}BiTNode,*BiTree;

//1、创建二叉链表：按先序次序输入二叉树中结点的值，创建二叉链表表示的二叉树T 
// 例：建立课本P115图5.10(b)的二叉树--读入字符的顺序为：ABC##DE#G##F###(#表示空树) 
BiTree Create(BiTree &T)
{
	char ch;
	printf("请输入一个字符:");
	scanf("%c",&ch);
	getchar();  //清空缓冲区，把遗留的\n清除 
	//todo list   //if: 如果输入的是'#'，则建立一棵空树
	//else：否则，递归建立一个二叉树（注意：是按按先序次序创建的二叉树）
	if(ch == '#') {
		T = NULL;  //建立空树
	} else {
		T = (BiTree)malloc(sizeof(BiTNode));  //创建新结点
		T->data = ch;
		T->lchild = NULL;
		T->rchild = NULL;
		T->lchild = Create(T->lchild);  //递归创建左子树
		T->rchild = Create(T->rchild);  //递归创建右子树
	}
	return T;
}

//先序遍历二叉树
Status  PreOrder(BiTree &T)
{
	//todo list   //if: 如果是空树，则返回
	//else:否则，先访问根结点 (D)
	//前序遍历左子树 (L)
	//前序遍历右子树 (R)
	if(T == NULL) {
		return OK;
	} else {
		printf("%c ", T->data);  //访问根结点
		PreOrder(T->lchild);     //前序遍历左子树
		PreOrder(T->rchild);     //前序遍历右子树
	}
	return OK;
}

//中序遍历二叉树 
Status InOrder(BiTree &T)
{
	//todo list   //if: 如果是空树，则返回
	//else:否则，先中序遍历左子树 (L)
	//访问根结点 (D)
	//中序遍历右子树 (R)
	if(T == NULL) {
		return OK;
	} else {
		InOrder(T->lchild);      //中序遍历左子树
		printf("%c ", T->data);  //访问根结点
		InOrder(T->rchild);      //中序遍历右子树
	}
	return OK;
}

//后序遍历
Status PostOrder(BiTree &T)
{
	//todo list   //if: 如果是空树，则返回
	//else:否则，先后序遍历左子树 (L)
	//后序遍历右子树 (R)
	//访问根结点 (D)
	if(T == NULL) {
		return OK;
	} else {
		PostOrder(T->lchild);    //后序遍历左子树
		PostOrder(T->rchild);    //后序遍历右子树
		printf("%c ", T->data);  //访问根结点
	}
	return OK;
}

//层次遍历1
void LeverOrder(BiTree &T)
{
	if (T == NULL) {  // 处理空树，避免空指针访问
        printf("二叉树为空！\n");
        return;
    }
	//BT *Queue[100]; //队列
	BiTree Queue[100]; //队列
	char ch;
	int front = 0;
	int rear = 0;
	// 队列边界检查（新增：防止数组越界）
    if (rear >= 100) {
        printf("队列已满，无法入队！\n");
        return;
    }
	Queue[rear++] = T; //根节点入队
	while (front < rear) //当队不空
	{
		ch = Queue[front]->data; //出队队头元素 
		printf("%c ",ch);
		if (Queue[front]->lchild){
			if (rear >= 100) {
            	printf("队列已满，左孩子无法入队！\n");
                break;
            }
			Queue[rear++] = Queue[front]->lchild;
		}
		if (Queue[front]->rchild){
			if (rear >= 100) {
	            printf("队列已满，右孩子无法入队！\n");
	            break;
	        }
			Queue[rear++] = Queue[front]->rchild;
		}
		front++;  // 队头后移，完成出队
	}
	
}

//节点总数
int Count(BiTree &T)
{
	//todo list    //if：如果是空树，则结点个数为0；
	//else：否则，结点个数为左子树的结点个数+右子树的结点个数再+1。
	if(T == NULL) {
		return 0;
	} else {
		return Count(T->lchild) + Count(T->rchild) + 1;
	}
}
//叶子节点
int CountLeaf(BiTree &T)
{
	//todo list    //if：如果是空树，则叶子结点个数为0；
	//else if：如果是叶子结点，则返回1；
	//else否则，为左子树的叶子结点个数+右子树的叶子结点个数。
	if(T == NULL) {
		return 0;
	} else if(T->lchild == NULL && T->rchild == NULL) {
		return 1;
	} else {
		return CountLeaf(T->lchild) + CountLeaf(T->rchild);
	}
}
int main()
{
	BiTree T = NULL;   //创建一颗空树
	int choose = -1;
	printf("*********************************************\n");
	printf("**********           实验六           *******\n");
	printf("*********************************************\n");
	printf("**********     1.创建一棵二叉树       *******\n");
	printf("**********     2.先序遍历二叉树       *******\n");
	printf("**********     3.中序遍历二叉树       *******\n");
	printf("**********     4.后序遍历二叉树       *******\n");
	printf("**********     5.层序遍历二叉树       *******\n");
	printf("**********     6.求二叉树节点个数     *******\n");
	printf("**********     7.求二叉数叶子节点个数 *******\n");
	printf("**********     0.退出                 *******\n");
	printf("*********************************************\n");
	while (choose)
	{
		printf("\n");
		printf("请输入你的选择项：");
		scanf("%d", &choose);
		getchar(); //清空缓冲区，把遗留的\n清除 
		switch (choose)
		{
		case 1:T = Create(T); break;  //创建
		printf("\n");
		case 2:
			printf("先序序列为：") ;
			PreOrder(T); break;   //先序遍历二叉树
			printf("\n");
		case 3:
			printf("中序序列为：") ;
			InOrder(T); break;   //中序遍历二叉树
			printf("\n");
		case 4:
			printf("后序序列为：") ;
			PostOrder(T); break;  //后序遍历二叉树
			printf("\n");
		case 5:
			printf("层次序列为：")	;		
			LeverOrder(T); break;   //层序遍历二叉树
			printf("\n");
		case 6:printf("节点总数为：%d\n", Count(T)); break;//结点总数
		case 7:printf("叶子节点总数为：%d\n", CountLeaf(T)); break; //叶子结点总数
		case 0:exit(0); break;
		}
	}
}
