/*
树
2018.12.20
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define element char
#define MAXSIZE 1000
typedef struct BinaryTreeNode
{
element data;
struct BinaryTreeNode *leftChild;
struct BinaryTreeNode *rightChild;
}BinaryTreeNode;
//创建二叉树(先序创建)
BinaryTreeNode *preCreate()
{
element input;
BinaryTreeNode *p;
//这里直接 %c前面加空格就好了,这样无论怎么输入(空多少格)都没有问题
scanf(" %c", &input); //这样调用scanf时,树的结点一次全部输入,如果要一次一个的输入,在%c前加个空格
if (input != '*')
{
p = (BinaryTreeNode*)malloc(sizeof(BinaryTreeNode));
p->data = input;
p->leftChild = preCreate();
p->rightChild = preCreate();
}
else
{
p = NULL;//如果输入的是 '*'
}
return p;
}
//前序遍历(递归实现)
/*
算法思想:
如果当前结点不为空
访问当前结点
前序遍历左子树
前序遍历右子树
*/
void preorder(BinaryTreeNode *p)
{
if (p != NULL)
{
printf("%c", p->data);//遍历操作,此处为打印数据元素
preorder(p->leftChild);
preorder(p->rightChild);
}
}
//中序遍历(递归实现)
/*
算法思想:
如果当前结点不为空
中序遍历左子树
访问当前结点
中序遍历右子树
*/
void inorder(BinaryTreeNode *p)
{
if (p != NULL)
{
inorder(p->leftChild);
printf("%c", p->data);
inorder(p->rightChild);
}
}
//后序遍历(递归实现)
/*
算法思想:
如果当前结点不为空
后序遍历左子树
后序遍历右子树
访问当前结点
*/
void postorder(BinaryTreeNode *p)
{
if (p != NULL)
{
postorder(p->leftChild);
postorder(p->rightChild);
printf("%c", p->data);
}
}
//层次遍历(循环队列)
/*
算法思想:
定义结点队列
如果当前结点不为空 //不是空树
根节点入队 //循环队列
while(队列非空)出队打印,左孩子入队之后,右孩子入队;
*/
void levelorder(BinaryTreeNode *p)
{
int front, rear;
front = rear = 0;
BinaryTreeNode *que[MAXSIZE];// 队列的简单定义,队列存放的是二叉树结点的地址
BinaryTreeNode *temp;
if (p != NULL)//当结点非空
{
rear = (rear + 1) % MAXSIZE;
que[rear] = p;//根节点入队
while (front != rear)//当队列非空
{
front = (front + 1) % MAXSIZE;
temp = que[front];//队头结点出队
printf("%c", temp->data);
if (temp->leftChild != NULL)//存在队头结点的左孩子,左孩子入队
{
rear = (rear + 1) % MAXSIZE;
que[rear] = temp->leftChild;
}
if (temp->rightChild != NULL)//存在队头结点的右孩子,右孩子入队
{
rear = (rear + 1) % MAXSIZE;
que[rear] = temp->rightChild;
}
}
}
}
//获取树高(递归实现)
/*
算法思想:
定义左子树高度、右子树高度
如果当前结点为空,返回0
否则 求左子树高度
求右子树高度
返回较高子树的高度+1 //加1是因为根节点
*/
int getDepth(BinaryTreeNode *p)
{
int leftDepth, rightDepth;
if (p == NULL)return 0;
else
{
leftDepth = getDepth(p->leftChild);
rightDepth = getDepth(p->rightChild);
return (leftDepth > rightDepth ? leftDepth : rightDepth) + 1;
}
}
//获取叶子(递归实现)
/*
算法思想:
如果当前结点不为空
如果左子树和右子树都不存在,打印数据
获取左子树的叶子
获取右子树的叶子
*/
void getLeaf(BinaryTreeNode *p)
{
if (p != NULL)
{
if (p->leftChild == NULL && p->rightChild == NULL)
printf("%c", p->data);
getLeaf(p->leftChild);
getLeaf(p->rightChild);
}
}
//前序遍历(非递归实现/自定义栈)
/*
算法思想:
如果根节点不为空
初始化栈,存储结点
根节点入栈
当栈不空:出栈打印,右孩子入栈之后,左孩子入栈
*/
void preorderNonRecursion(BinaryTreeNode *bt)
{
if (bt != NULL)
{
BinaryTreeNode *stack[MAXSIZE];
int top = -1;//初始化栈
BinaryTreeNode *p = NULL;
stack[++top] = bt;//根结点入栈
while (top != -1 )
{
p = stack[top--];//出栈
printf("%c", p->data);//打印
if (p->rightChild != NULL)//右孩子先入栈
stack[++top] = p->rightChild;
if (p->leftChild != NULL)//左孩子后入栈
stack[++top] = p->leftChild;
}
}
}
//中序遍历(非递归实现/自定义栈)
/*
算法思想:
如果根节点不为空
初始化栈,存储结点
当栈非空 或 结点非空
当结点非空:入栈读左子 //一直读到底
如果栈非空:出栈打印读右子
*/
void inorderNonRecursion(BinaryTreeNode *bt)
{
if (bt!= NULL)
{
BinaryTreeNode *stack[MAXSIZE];
int top = -1;//栈初始化
BinaryTreeNode *p;
p = bt;
while (top != -1 || p != NULL)//当读取根节点的右子树时,栈空top = -1
{ //但此时 temp = 根->rightChild != NULL
while (p != NULL)
{
stack[++top] = p;
p = p->leftChild;
}
if (top != -1)
{
p = stack[top--];
printf("%c", p->data);
p = p->rightChild;
}
}
}
}
//后序遍历(非递归实现/自定双栈)
/*
算法思想:
如果根结点不为空
定义双栈
根节点入栈1
当栈1非空:栈1出栈入栈2,左子非空入栈1,右子非空入栈1 //入栈1的顺序与前序遍历非递归相反 逆后序遍历序列
当栈2非空:栈2出栈得后序遍历顺序 // 前序遍历非递归为先入栈右子,后入栈左子
*/
void postorderNonRecursion(BinaryTreeNode *bt)
{
if (bt != NULL)//树非空
{
//双栈的定义
BinaryTreeNode *stack1[MAXSIZE]; int top1 = -1;
BinaryTreeNode *stack2[MAXSIZE]; int top2 = -1;
BinaryTreeNode *p = NULL;
stack1[++top1] = bt;
while (top1 != -1)//stack1辅助建立逆后序遍历序列,逆后序遍历序列全部入栈stack2
{
p = stack1[top1--];
stack2[++top2] = p;
if (p->leftChild != NULL)
stack1[++top1] = p->leftChild;
if (p->rightChild != NULL)
stack1[++top1] = p->rightChild;
}
while (top2 != -1)//stack2中的逆后序遍历序列出栈,得到后序遍历顺序
{
p = stack2[top2--];
printf("%c", p->data);
}
}
}
int main()
{
/*
输入序列:
ABD*G***CE**FH***
*/
BinaryTreeNode *p = preCreate();
printf("\n前序遍历:"); preorder(p);
printf("\n中序遍历:"); inorder(p);
printf("\n后序遍历:"); postorder(p);
printf("\n层次遍历:"); levelorder(p);
printf("\n树的高度:%d",getDepth(p));
printf("\n树的叶子:"); getLeaf(p);
printf("\n【非递归实现/自定义栈】前序遍历:"); preorderNonRecursion(p);
printf("\n【非递归实现/自定义栈】中序遍历:"); inorderNonRecursion(p);
printf("\n【非递归实现/自定双栈】后序遍历:"); postorderNonRecursion(p);
return 0;
}