这篇文章给出了这道题的代码实现方式。
代码对可能的问题给出了详尽的注释,如果读者还有不明白的地方,欢迎在评论区留下你的问题。
#include <stdio.h>
#define ElemType int //二叉排序树存储数据Data类型为ElemType:int
#define Status int //函数返回状态
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef struct BiTNode //定义二叉树结点类型
{
ElemType Data;
struct BiTNode *Lchild, *Rchild;
} BiTNode, *BiTree;
void InsertElem(BiTree &T, ElemType e) //插入函数:对每一个结点找到其合适位置并插入
{
if (!T) //找到空节点
{
T = new BiTNode;
T->Data = e;
T->Lchild = T->Rchild = NULL;
}
else
{
if (T->Data > e)
InsertElem(T->Lchild, e); //根据当前节点值与待插入值之间的大小关系,分别向左向右寻找
else
InsertElem(T->Rchild, e);
}
}
void Create(BiTree &T, int ElemNum) //构建二叉排序树
{
for (int i = 0; i < ElemNum; i++)
{
ElemType Element;
scanf("%d", &Element);
InsertElem(T, Element); //插入每一个输入的值
}
}
void PreOrderTraverse(BiTree T) //先序遍历的递归算法
{
if (T)
{
printf("%d ", T->Data);
PreOrderTraverse(T->Lchild);
PreOrderTraverse(T->Rchild);
}
}
void InOrderTraverse(BiTree T) //中序遍历的递归算法
{
if (T)
{
InOrderTraverse(T->Lchild);
printf("%d ", T->Data);
InOrderTraverse(T->Rchild);
}
}
void PostOrderTraverse(BiTree T) //后序遍历的递归算法
{
if (T)
{
PostOrderTraverse(T->Lchild);
PostOrderTraverse(T->Rchild);
printf("%d ", T->Data);
}
}
void Traverse(BiTree T) //依次进行先序、中序、后序遍历
{
PreOrderTraverse(T);
printf("\n");
InOrderTraverse(T);
printf("\n");
PostOrderTraverse(T);
printf("\n");
}
Status Search(BiTree T, ElemType key) //寻找key的算法
{
if (!T)
return FALSE; //没有找到key值,返回FALSE
else
{
if (T->Data == key)
return TRUE; //找到key值,返回TRUE
else if (T->Data > key)
return Search(T->Lchild, key);
else
return Search(T->Rchild, key); //依次往左右子树寻找key值
}
}
struct Stack //定义栈结构,用于二叉排序树的中序遍历的非递归实现
{
BiTree base, top;
int StackSize;
};
void InitStack(Stack &S, int MAXSIZE) //栈的初始化
{
S.base = new BiTNode[MAXSIZE];
S.top = S.base;
S.StackSize = MAXSIZE;
}
Status StackEmpty(Stack S) //判断栈空函数,空则返回TRUE,非空则返回FALSE
{
if (S.top == S.base)
return TRUE;
else
return FALSE;
}
Status Push(Stack &S, BiTNode e) //栈顶插入元素e
{
if (S.top - S.base == S.StackSize)
return ERROR; //栈满
else
{
*S.top = e;
S.top++;
}
}
Status Pop(Stack &S, BiTNode &e) //删除栈顶元素并返回给e
{
if (StackEmpty(S))
return ERROR; //栈空
else
{
S.top--;
e = *S.top;
}
}
void InOrderTraverse_by_Stack(BiTree T, Stack &S) //中序遍历的非递归算法:利用栈实现
{
BiTree Temp1 = T; //Temp1用于从根结点开始,依次访问每一个结点
BiTNode Temp2; //Temp2用于访问每一个结点的值
while (Temp1 || !StackEmpty(S)) //当前结点不为NULL或者栈内仍有结点时,继续遍历
{
if (Temp1) //树结点非空,将其入栈,并继续访问其左子树
{
Push(S, *Temp1);
Temp1 = Temp1->Lchild;
}
else
{
Pop(S, Temp2);
printf("%d ", Temp2.Data); //左子树为空,输出其值,并开始访问其右子树
Temp1 = Temp2.Rchild;
}
}
}
struct Queue //定义队列结构,实现二叉排序树的层次遍历,
{
BiTree base;
int front, rear, MAXQSIZE;
};
void InitQueue(Queue &Q, int MAXQSIZE) //队列初始化
{
Q.base = new BiTNode[MAXQSIZE];
Q.front = Q.rear = 0;
Q.MAXQSIZE = MAXQSIZE;
}
Status QueueEmpty(Queue Q) //判断队列是否为空
{
if (Q.rear == Q.front)
return TRUE;
else
return FALSE;
}
Status GetHead(Queue &Q, BiTNode &e) //返回队列头元素给e
{
if (QueueEmpty(Q))
return ERROR;
else
e = Q.base[Q.front];
}
Status InQueue(Queue &Q, BiTNode e) //队列尾插入元素
{
if ((Q.rear + 1) % Q.MAXQSIZE == Q.front)
return ERROR;
else
{
Q.base[Q.rear] = e;
Q.rear = (Q.rear + 1) % Q.MAXQSIZE;
}
}
Status DeQueue(Queue &Q) //删除队列头元素
{
if (QueueEmpty(Q))
return ERROR;
else
Q.front = (Q.front + 1) % Q.MAXQSIZE;
}
void LevelTraverse(BiTree T, Queue &Q) //二叉树的层次遍历
{
BiTNode Temp; //Temp用于访问每一个结点的值
InQueue(Q, *T); //将根结点入队
while (!QueueEmpty(Q)) //队列非空时,继续遍历
{
GetHead(Q, Temp);
printf("%d ", Temp.Data);
if (Temp.Lchild)
InQueue(Q, *(Temp.Lchild));
if (Temp.Rchild)
InQueue(Q, *(Temp.Rchild));
DeQueue(Q);
}
}
void ChangeBiTNode(BiTree T) //交换二叉树的左右子树算法
{
if (T) //先对左子树交换其左右子树,再对右子树交换其左右子树,最后对其本身交换左右子树,递归调用即可
{
ChangeBiTNode(T->Lchild);
ChangeBiTNode(T->Rchild);
BiTree Temp = T->Lchild;
T->Lchild = T->Rchild;
T->Rchild = Temp;
}
}
int BiTreeDepth(BiTree T) //求二叉树深度算法
{
if (!T)
return 0; //空子树深度为0
else
{
int LchildDepth = BiTreeDepth(T->Lchild);
int RchildDepth = BiTreeDepth(T->Rchild);
if (LchildDepth > RchildDepth)
return LchildDepth + 1;
else
return RchildDepth + 1;
} //对于每一棵二叉排序树,其深度等于其左右子树中较深的一棵加上其本身的深度1,递归调用即可
}
int LeafNum = 0;
void LeafNumCount(BiTree T) //叶子结点统计算法
{
if (T)
{
if (!T->Lchild && !T->Rchild)
LeafNum++;
LeafNumCount(T->Lchild);
LeafNumCount(T->Rchild);
}
}
int main()
{
int ElemNum;
scanf("%d", &ElemNum); //输入第一行:结点个数
BiTree T = NULL; //初始化根节点为NULL
Create(T, ElemNum); //根据输入构建二叉排序树
Traverse(T); //输出第一行到第三行
ElemType TargetNum1, TargetNum2;
scanf("%d", &TargetNum1); //输入第三行:第一个待查找结点
scanf("%d", &TargetNum2); //输入第四行:第二个待查找结点
printf("%d\n", Search(T, TargetNum1)); //输出第四行:是否找到第一个结点值
printf("%d\n", Search(T, TargetNum2)); //输出第五行:是否找到第二个结点值
ElemType Data_to_Insert;
scanf("%d", &Data_to_Insert); //输入第五行:待插入结点
InsertElem(T, Data_to_Insert); //插入新结点
Traverse(T); //输出第六行到第八行
Stack S;
InitStack(S, ElemNum); //初始化一个栈,存储元素为二叉排序树结点
InOrderTraverse_by_Stack(T, S); //输出第九行:插入新结点后的二叉树中序遍历的非递归形式
printf("\n");
Queue Q;
InitQueue(Q, ElemNum); //初始化一个队列,存储元素为二叉排序树结点
LevelTraverse(T, Q); //输出第十行:插入新结点后的二叉树层次遍历序列
printf("\n");
ChangeBiTNode(T); //第一次交换左右子树
Traverse(T); //输出第十一到十三行
ChangeBiTNode(T); //第二次交换左右子树
Traverse(T); //输出第十四到十六行
printf("%d\n", BiTreeDepth(T)); //输出第十七行:二叉树的深度
LeafNumCount(T);
printf("%d", LeafNum); //输出第十八行:叶子结点数
return 0;
}