二叉树 抽象数据类型实现

该博客介绍了如何实现二叉树的创建、销毁、遍历(先序、中序、后序、层次)及辅助功能如深度计算、叶子节点计数。通过C语言代码展示了二叉树的基本操作,并提供了用户交互界面供测试。此外,还包含了一个错误检查的函数以确保用户输入整数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



代码

函数接口定义

#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;
}

测试用例&运行结果

  1. JA#HDC##F###ML##P#Y##
    测试用例1

先序遍历:
在这里插入图片描述

中序遍历:
在这里插入图片描述

后序遍历:
在这里插入图片描述

层次遍历:
在这里插入图片描述

深度:
在这里插入图片描述

叶子结点数:
在这里插入图片描述

  1. FA#CB###PI#L###
    测试用例2

  2. A#C#D#FE##Y##
    测试用例3


其余测试用例读者可自行测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不要做码农呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值