二叉树(数据结构)(VS)(C语言)(BinaryTree)


0.前言

  这是我由C语言写的二叉树,希望对大家有帮助。


1.BinaryTree.h

#pragma once

#define _CRT_SECURE_NO_WARNINGS 1
//_CRT_SECURE_NO_WARNINGS

// 定义头文件
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>

// 定义存储的数据类型
typedef char BTDataType;

// 定义二叉树的节点
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTN, BT;

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTN* BinaryTreeCreate(BTDataType* a, int* pi);
// 二叉树销毁
void BinaryTreeDestroy(BTN** root);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTN* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTN* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTN* root);
// 层序遍历
void BinaryTreeLevelOrder(BTN* root);
// 二叉树节点个数
size_t BinaryTreeSize(BTN* root);
// 二叉树节深度
size_t BinaryTreeHeight(BTN* root);
// 二叉树查找值为x的节点
BTN* BinaryTreeFind(BTN* root, const BTDataType x);
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTN* root);
// 二叉树第k层节点个数
size_t BinaryTreeLevelKSize(BTN* root, int k);
// 二叉树叶子节点个数
size_t BinaryTreeLeafSize(BTN* root);

2.BinaryTree.c

#include "BinaryTree.h"
#include "Queue.h"

// 买一个节点
static BTN* BugNode(const BTDataType x)
{
	BTN* new_node = (BTN*)malloc(sizeof(BTN));
	assert(new_node);
	new_node->data = x;
	new_node->left = NULL;
	new_node->right = NULL;
	return new_node;
}

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTN* BinaryTreeCreate(BTDataType* a, int* pi)
{
	if (a[*pi] == '#')
	{
		(*pi)++;
		return NULL;
	}
	BTN* new_node = BugNode(a[(*pi)++]);
	new_node->left = BinaryTreeCreate(a, pi);
	new_node->right = BinaryTreeCreate(a, pi);
	return new_node;
}

// 二叉树销毁
void BinaryTreeDestroy(BTN** root)
{
	assert(root);
	if (!*root)
	{
		return;
	}
	BinaryTreeDestroy(&(*root)->left);
	BinaryTreeDestroy(&(*root)->right);
	free(*root);
	*root = NULL;
}

// 二叉树前序遍历	
void BinaryTreePrevOrder(BTN* root)
{
	if(!root)
	{
		printf("NULL ");
		return;
	}
	printf("%c ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}

// 二叉树中序遍历
void BinaryTreeInOrder(BTN* root)
{
	if (!root)
	{
		printf("NULL ");
		return;
	}
	BinaryTreeInOrder(root->left);
	printf("%c ", root->data);
	BinaryTreeInOrder(root->right);
}

// 二叉树后序遍历
void BinaryTreePostOrder(BTN* root)
{
	if (!root)
	{
		printf("NULL ");
		return;
	}
	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%c ", root->data);
}

// 层序遍历
void BinaryTreeLevelOrder(BTN* root)
{
	Q q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTN* front = QueueFront(&q);
		QueuePop(&q);
		printf("%c ", front->data);
		if (front->left)
			QueuePush(&q, front->left);
		if (front->right)
			QueuePush(&q, front->right);
	}
	printf("\n");
	QueueDestroy(&q);
}

// 二叉树节点个数
size_t BinaryTreeSize(BTN* root)
{
	return !root ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

// 二叉树节深度
size_t BinaryTreeHeight(BTN* root)
{
	if (!root)
		return 0;
	size_t left = BinaryTreeHeight(root->left);
	size_t right = BinaryTreeHeight(root->right);
	return left > right ? left + 1 : right + 1;
}

// 二叉树查找值为x的节点
BTN* BinaryTreeFind(BTN* root, const BTDataType x)
{
	if (!root)
		return NULL;
	if (root->data == x)
		return root;
	// 找左
	BTN* left = BinaryTreeFind(root->left, x);
	if (left)
		return left;
	BTN* right = BinaryTreeFind(root->right, x);
	// 找右
	if (right)
		return right;
	// 找不到
	else
		return NULL;
}

// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTN* root)
{
	Q q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTN* front = QueueFront(&q);
		QueuePop(&q);
		if (!front)
			break;
		QueuePush(&q, front->left);
		QueuePush(&q, front->right);
	}
	while (!QueueEmpty(&q))
	{
		BTN* front = QueueFront(&q);
		QueuePop(&q);
		if (front)
		{
			QueueDestroy(&q);
			return false;
		}
	}
	QueueDestroy(&q);
	return true;
}

// 二叉树第k层节点个数
size_t BinaryTreeLevelKSize(BTN* root, int k)
{
	assert(k > 0);
	if (!root)
		return 0;
	if (k == 1)
		return 1;
	return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}

// 二叉树叶子节点个数
size_t BinaryTreeLeafSize(BTN* root)
{
	Q q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	int n = 0;
	while (!QueueEmpty(&q))
	{
		BTN* front = QueueFront(&q);
		QueuePop(&q);
		if (!front->left && !front->right)
			n++;
		if (front->left)
			QueuePush(&q, front->left);
		if (front->right)
			QueuePush(&q, front->right);
	}
	QueueDestroy(&q);
	return n;
}

3.Queue.h

这里我用是我以前写的线性表之栈和队列中的队列

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
//_CRT_SECURE_NO_WARNINGS

// 定义头文件
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#include "BinaryTree.h"

// 支持动态增长的栈
typedef BTN* QDataType;
// 链式结构:表示队列 
typedef struct QListNode
{
	QDataType data;
	struct QListNode* next;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* head;
	QNode* tail;
	size_t size;
}Queue, Q;

// 初始化队列 
void QueueInit(Queue* pq);
// 销毁队列 
void QueueDestroy(Queue* pq);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* pq);
// 队尾入队列 
void QueuePush(Queue* pq,const QDataType x);
// 队头出队列 
void QueuePop(Queue* pq);
// 获取队列头部元素 
QDataType QueueFront(Queue* pq);
// 获取队列队尾元素 
QDataType QueueBack(Queue* pq);
// 获取队列中有效元素个数 
size_t QueueSize(Queue* pq);

4.Queue.c

#include "Queue.h"

// 初始化队列 
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}
// 销毁队列 
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* node = pq->head;
	while (node)
	{
		QNode* tmp_node = node;
		node = node->next;
		free(tmp_node);
	}
	pq->head = pq->tail = NULL;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* pq)
{
	return pq->head == NULL;
}
// 队尾入队列 
void QueuePush(Queue* pq, const QDataType x)
{
	assert(pq);
	QNode* new_node = (QNode*)malloc(sizeof(QNode));
	if (!new_node)
	{
		perror("BuyQNode");
		exit(-1);
	}
	new_node->data = x;
	new_node->next = NULL;
	if (QueueEmpty(pq))
	{
		pq->tail = pq->head = new_node;
	}
	else
	{
		pq->tail->next = new_node;
		pq->tail = pq->tail->next;
	}
	pq->size++;
}
// 队头出队列 
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	if (!pq->head->next)
	{
		free(pq->head);
		pq->tail = pq->head = NULL;
	}
	else
	{
		QNode* tmo_node = pq->head;
		pq->head = pq->head->next;
		free(tmo_node);
	}
	pq->size--;
}
// 获取队列头部元素 
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}
// 获取队列中有效元素个数 
size_t QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

5.BinaryTreeTest.c

#include "BinaryTree.h"

void BinaryTreeTest()
{
    char str[100] = "12##3##"; // "abc##de#g##f###";
    printf("请入以通过前序遍历的数组“ABD##E#H##CF##G##”构建二叉树的字符串:");
    scanf("%s", str);
    int i = 0;
    BT* root = BinaryTreeCreate(str, &i);
    BinaryTreePrevOrder(root);
    printf("\n");
    BinaryTreeInOrder(root);
    printf("\n");
    BinaryTreePostOrder(root);
    printf("\n");
    BinaryTreeLevelOrder(root);
    printf("BinarySize:%d\n", (int)BinaryTreeSize(root));
    printf("BinaryHeight:%d\n", (int)BinaryTreeHeight(root));
    printf("BinaryTreeLevelKSize: %d\n", (int)BinaryTreeLevelKSize(root, 1));
    printf("BinaryTreeLevelKSize: %d\n", (int)BinaryTreeLevelKSize(root, 2));
    printf("BinaryTreeLevelKSize: %d\n", (int)BinaryTreeLevelKSize(root, 3));
    BTN* pos = BinaryTreeFind(root, 'a');
    if (pos)
        printf("BinaryTreeFind:%c,找到了。\n", pos->data);
    else
        printf("找不到了。\n");
    pos = BinaryTreeFind(root, 'c');
    if (pos)
        printf("BinaryTreeFind:%c,找到了。\n", pos->data);
    else
        printf("找不到了。\n");
    pos = BinaryTreeFind(root, 'z');
    if (pos)
        printf("BinaryTreeFind:%c,找到了。\n", pos->data);
    else
        printf("找不到了。\n");
    if (BinaryTreeComplete(root))
        printf("isBinaryTreeComplete\n");
    else
        printf("noBinaryTreeComplete\n");
    printf("BinaryTreeLeafSize:%d\n", BinaryTreeLeafSize(root));
    BinaryTreeDestroy(&root);
}

int main(void)
{
    BinaryTreeTest();
    return 0;
}

6.效果

在这里插入图片描述


看完给个关注,多谢了!!!

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值