代码
函数接口定义
#pragma once
#ifndef BiTree_H_INCLUDED
#define BiTree_H_INCLUDED
/* 函数结果状态 */
typedef enum Status
{
error,
success
} Status;
typedef char ElemType;
/* 二叉树结点定义 */
typedef struct BiTNode
{
ElemType data; //数据域
struct BiTNode* lchild, * rchild; //指针域,二叉链表
}BiTNode, * BiTree;
/* 队列结点定义 */
typedef struct LQueueNode {
BiTree data; //数据域
struct LQueueNode* next; //指针域
}LQueueNode;
/* 队列定义 */
typedef struct LQueue {
LQueueNode* front; //队头指针
LQueueNode* rear; //队尾指针
}LQueue, * pLQueue;
/* 销毁二叉树 */
void DestroyBiTree(BiTree* T);
/* 构造二叉树 */
Status CreateBiTree(BiTree* T, char* definition);
/* 先序遍历 */
void PreOrderTraverse(BiTree T, void(*visit)(ElemType e));
/* 中序遍历 */
void InOrderTraverse(BiTree T, void(*visit)(ElemType e));
/* 后序遍历 */
void PostOrderTraverse(BiTree T, void(*visit)(ElemType e));
/* 层次遍历 */
void LevelOrderTraverse(BiTree T, void(*visit)(ElemType e));
/* 初始化空队列 */
pLQueue InitLQueue(pLQueue Q);
/* 入队 */
Status EnLQueue(pLQueue Q, BiTree node);
/* 出队 */
BiTree DeLQueue(pLQueue Q);
/* 访问结点 */
void visit(ElemType e);
/* 求二叉树的深度 */
int BiTreeDepth(BiTree T);
/* 计算叶子结点数 */
void CountLeaf(BiTree T, int* count);
/* 显示界面 */
void show(void);
/* 规范用户输入整数 */
int judge_int(void);
#endif
实现接口的功能
#include "BiTree.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void DestroyBiTree(BiTree* T)
{
if (*T != NULL)
{
DestroyBiTree(&((*T)->lchild));
DestroyBiTree(&((*T)->rchild));
free(*T);
}
}
Status CreateBiTree(BiTree* T, char* definition)
{
definition = (char*)malloc(sizeof(char));
if (definition == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
*definition = getchar();
if (*definition == '#')
{
*T = NULL;
return error;
}
else
{
*T = (BiTree)malloc(sizeof(BiTNode));
if (*T == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
(*T)->data = *definition;
CreateBiTree(&(*T)->lchild, definition);
CreateBiTree(&(*T)->rchild, definition);
return success;
}
}
void PreOrderTraverse(BiTree T, void(*visit)(ElemType e))
{
if (T != NULL)
{
visit(T->data);
PreOrderTraverse(T->lchild, visit);
PreOrderTraverse(T->rchild, visit);
}
}
void InOrderTraverse(BiTree T, void(*visit)(ElemType e))
{
if (T != NULL)
{
InOrderTraverse(T->lchild, visit);
visit(T->data);
InOrderTraverse(T->rchild, visit);
}
}
void PostOrderTraverse(BiTree T, void(*visit)(ElemType e))
{
if (T != NULL)
{
PostOrderTraverse(T->lchild, visit);
PostOrderTraverse(T->rchild, visit);
visit(T->data);
}
}
pLQueue InitLQueue(pLQueue Q)
{
Q = (pLQueue)malloc(sizeof(LQueue));
if (Q == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
Q->front = Q->rear = NULL;
return Q;
}
Status EnLQueue(pLQueue Q, BiTree node)
{
LQueueNode* QNode = (LQueueNode*)malloc(sizeof(LQueueNode));
if (QNode == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
QNode->data = (BiTree)malloc(sizeof(BiTNode));
if (QNode->data == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
memcpy(QNode->data, node, sizeof(BiTNode));
QNode->next = NULL;
if (Q->front == NULL)
{
Q->front = QNode;
Q->rear = QNode;
}
else
{
Q->rear->next = QNode;
Q->rear = QNode;
}
return success;
}
BiTree DeLQueue(pLQueue Q)
{
BiTree BNode = (BiTree)malloc(sizeof(BiTNode));
if (BNode == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
LQueueNode* temp = Q->front;
BNode = temp->data;
if (Q->front == Q->rear)
{
Q->front = Q->rear = NULL;
}
else
{
Q->front = temp->next;
}
free(temp);
return BNode;
}
void LevelOrderTraverse(BiTree T, void(*visit)(ElemType e))
{
pLQueue Q = NULL;
Q = InitLQueue(Q);
EnLQueue(Q, T);
while (Q->front != NULL)
{
BiTree BNode = (BiTree)malloc(sizeof(BiTNode));
if (BNode == NULL)
{
printf("内存分配失败\n");
system("pause");
exit(0);
}
BNode = DeLQueue(Q);
visit(BNode->data);
if (BNode->lchild != NULL)
{
EnLQueue(Q, BNode->lchild);
}
if (BNode->rchild != NULL)
{
EnLQueue(Q, BNode->rchild);
}
free(BNode);
}
free(Q);
}
void visit(ElemType e)
{
printf("%c\t", e);
}
int BiTreeDepth(BiTree T)
{
int depthLeft, depthRight;
if (T == NULL)
{
return 0;
}
else
{
depthLeft = BiTreeDepth(T->lchild);
depthRight = BiTreeDepth(T->rchild);
if (depthLeft > depthRight)
{
return depthLeft + 1;
}
else
{
return depthRight + 1;
}
}
}
void CountLeaf(BiTree T, int* count)
{
if (T != NULL)
{
if (T->lchild == NULL && T->rchild == NULL)
{
(*count)++;
}
CountLeaf(T->lchild, count);
CountLeaf(T->rchild, count);
}
}
void show(void)
{
printf("\n\n\n");
printf("************************************\n");
printf("* 二叉树 *\n");
printf("*----------------------------------*\n");
printf("* 1 | 构造二叉树 *\n");
printf("*----------------------------------*\n");
printf("* 2 | 销毁二叉树 *\n");
printf("*----------------------------------*\n");
printf("* 3 | 先序遍历 *\n");
printf("*----------------------------------*\n");
printf("* 4 | 中序遍历 *\n");
printf("*----------------------------------*\n");
printf("* 5 | 后序遍历 *\n");
printf("*----------------------------------*\n");
printf("* 6 | 层次遍历 *\n");
printf("*----------------------------------*\n");
printf("* 7 | 求二叉树的深度 *\n");
printf("*----------------------------------*\n");
printf("* 8 | 计算叶子结点数 *\n");
printf("*----------------------------------*\n");
printf("* 0 | 退出 *\n");
printf("************************************");
printf("\n请输入对应的数字(0-8):");
}
int judge_int(void) //防止用户乱输入其他的字符,规范用户输入整数
{
int len, num = 0, arg = 1;
char word[10] = {0};
int m, j = 1, k;
while (j)
{
scanf("%s", word);
len = strlen(word);
for (m = 0;m < len;m++)
{
if (word[m] < '0' || word[m]>'9') //检验是否有乱输入其他字符
{
printf("请输入整数:");
break;
}
else
{
if (m == len - 1)
j = 0;
}
}
}
j = len - 1;
for (m = 0;m < len;m++) // 将字符重新转换为数字
{
for (k = 0;k < j;k++)
arg *= 10;
num += (word[m] - '0') * arg;
arg = 1;
j--;
}
return num;
}
主程序入口
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include "BiTree.h"
int main(void)
{
int choice = 0;
BiTree T = NULL;
char* definition = NULL;
int isEmpty = 1;
do
{
show();
choice = judge_int();
system("cls");
switch (choice)
{
case 0: break; //跳出循环结束程序
case 1: //构造二叉树
{
if (isEmpty)
{
getchar();
printf("请输入表达式(#表示空结点):\n");
if (CreateBiTree(&T, definition))
{
isEmpty = 0;
printf("二叉树构造完成\n");
}
else
{
printf("二叉树构造失败\n");
}
}
else
{
printf("二叉树非空,请先销毁二叉树\n");
}
break;
}
case 2: //销毁二叉树
{
if (!isEmpty)
{
DestroyBiTree(&T);
isEmpty = 1;
printf("二叉树销毁完成");
}
else
{
printf("二叉树为空,无需销毁\n");
}
break;
}
case 3: //先序遍历
{
if (isEmpty)
{
printf("二叉树为空\n");
}
else
{
PreOrderTraverse(T, visit);
}
break;
}
case 4: //中序遍历
{
if (isEmpty)
{
printf("二叉树为空\n");
}
else
{
InOrderTraverse(T, visit);
}
break;
}
case 5: //后序遍历
{
if (isEmpty)
{
printf("二叉树为空\n");
}
else
{
PostOrderTraverse(T, visit);
}
break;
}
case 6: //层次遍历
{
if (isEmpty)
{
printf("二叉树为空\n");
}
else
{
LevelOrderTraverse(T, visit);
}
break;
}
case 7: //二叉树深度
{
if (isEmpty)
{
printf("二叉树为空,深度为0\n");
}
else
{
int depth = BiTreeDepth(T);
printf("二叉树深度为%d", depth);
}
break;
}
case 8: //叶子结点数
{
if (isEmpty)
{
printf("二叉树为空,叶子结点数为0\n");
}
else
{
int count = 0;
CountLeaf(T, &count);
printf("叶子结点数为%d", count);
}
break;
}
default: {
printf("输入有误,请重新输入\n");
break;
}
}
}while (choice != 0);
printf("\n\n\n\n\t\t感谢使用\n\n\n\n\n\n\n\n\n");
system("pause");
return 0;
}
测试用例&运行结果
- JA#HDC##F###ML##P#Y##
先序遍历:
中序遍历:
后序遍历:
层次遍历:
深度:
叶子结点数:
-
FA#CB###PI#L###
-
A#C#D#FE##Y##
其余测试用例读者可自行测试。