在阅读本文前, 请先阅读以下两篇文章.
一. 二叉树的定义 & 结构
二叉树的定义
一棵二叉树是节点的一个有限集合, 该集合或者为空, 或者由一个根节点加上两棵别称为左子树和右子树的二叉树组成.
二叉树的结构
子结构
对于任意的二叉树都是由以下几种情况复合而成的.
特殊二叉树
满二叉树: 一个二叉树, 如果每一个层的节点数都达到最大值, 则这个二叉树就是满二叉树. 也就是说, 如果一个二叉树的层数为 K, 且节点总数是 2^K - 1, 则它就是满二叉树.
完全二叉树: 深度为 k, 有 n 个节点的二叉树当且仅当其每一个节点都与深度为 k 的满二叉树中编号从1 到 n 的节点一一对应时, 称其为完全二叉树.
二. 二叉树各种接口的实现
此处的二叉树采用链式存储的结构实现.
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
1. 创建一个二叉树节点
BTNode* BuyNode(BTDataType x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if (node == NULL) {
perror("malloc fail");
return NULL;
}
node->data = x;
node->left = NULL;
node->right = NULL;
return node;
}
2. 销毁二叉树
采用后序遍历(左右根)的方式销毁二叉树.
void TreeDestroy(BTNode* root)
{
if (root == NULL) return;
TreeDestroy(root->left);
TreeDestroy(root->right);
free(root);
}
3. 前序遍历
前序遍历, 即访问根节点的操作发生在遍历其左右子树之前.
void PreOrder(BTNode* root)
{
if (root == NULL) {
printf("NULL ");
return;
}
printf("%d ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
4. 中序遍历
中序遍历, 即访问根节点的操作发生在遍历其左右子树之中.
void InOrder(BTNode* root)
{
if (root == NULL) {
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->data);
InOrder(root->right);
}
5. 后序遍历
后序遍历, 即访问根节点的操作发生在遍历其左右子树之后.
void PostOrder(BTNode* root)
{
if (root == NULL) {
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->data);
}
6. 二叉树节点个数
int TreeSize(BTNode* root)
{
return root == NULL ? 0 :
TreeSize(root->left)
+ TreeSize(root->right)
+ 1;
}
7. 二叉树高度
int TreeHeight(BTNode* root)
{
if (root == NULL) return 0;
int leftHeight = TreeHeight(root->left);
int rightHeight = TreeHeight(root->right);
return leftHeight > rightHeight ?
leftHeight + 1 : rightHeight + 1;
}
8. 二叉树第k层节点个数
int TreeLevelKSize(BTNode* root, int k)
{
assert(k > 0);
if (root == NULL) return 0;
if (k == 1) return 1;
return TreeLevelKSize(root->left, k - 1)
+ TreeLevelKSize(root->right, k - 1);
}
9. 查找值为 x 的节点
BTNode* TreeFind(BTNode* root, BTDataType x)
{
if (root == NULL) return NULL;
if (root->data == x) return root;
BTNode* lret = TreeFind(root->left, x);
if (lret) return lret;
BTNode* rret = TreeFind(root->right, x);
if (rret) return rret;
return NULL;
}
将 Queue.h 中的 typedef int QDataType; 改为 typedef struct BinaryTreeNode* QDataType;
10. 层序遍历
根节点不为空, 执行 if 语句的内容.
QueuePush(&q, root);
队列不为空, 进入 while 循环.
BTNode* front = QueueFront(&q);
QueuePop(&q);
printf("%d ", front->data);
front 节点左孩子不为空, 将左孩子入队.
QueuePush(&q, front->left);
front 节点右孩子不为空, 将右孩子入队.
QueuePush(&q, front->right);
重复这一步骤, 直至队列为空.
void LevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root) QueuePush(&q, root);
while (!QueueEmpty(&q)) {
BTNode* front = QueueFront(&q);
QueuePop(&q);
printf("%d ", front->data);
if (front->left) {
QueuePush(&q, front->left);
}
if (front->right) {
QueuePush(&q, front->right);
}
}
QueueDestroy(&q);
}
11. 判断二叉树是否是完全二叉树
bool TreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root) QueuePush(&q, root);
while (!QueueEmpty(&q)) {
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front == NULL) {
break;
} else {
QueuePush(&q, front->left);
QueuePush(&q, front->right);
}
}
// 开始判断是否是完全二叉树
while (!QueueEmpty(&q)) {
BTNode* front = QueueFront(&q);
QueuePop(&q);
// 出现非空节点, 说明非空节点不连续
if (front) {
QueueDestroy(&q);
return false;
}
}
QueueDestroy(&q);
return true;
}
三. 二叉树的源码
BinaryTree.h
#pragma once
#include "Queue.h"
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data; // 数据域
struct BinaryTreeNode* left; // 左孩子
struct BinaryTreeNode* right; // 右孩子
}BTNode;
// 创建一个二叉树节点
BTNode* BuyNode(BTDataType x);
// 销毁二叉树
void TreeDestroy(BTNode* root);
// 前序遍历
void PreOrder(BTNode* root);
// 中序遍历
void InOrder(BTNode* root);
// 后序遍历
void PostOrder(BTNode* root);
// 二叉树节点个数
int TreeSize(BTNode* root);
// 二叉树高度
int TreeHeight(BTNode* root);
// 二叉树第k层节点个数
int TreeLevelKSize(BTNode* root, int k);
// 查找值为 x 的节点
BTNode* TreeFind(BTNode* root, BTDataType x);
// 层序遍历
void LevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
bool TreeComplete(BTNode* root);
BinaryTree.c
#include "BinaryTree.h"
BTNode* BuyNode(BTDataType x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if (node == NULL) {
perror("malloc fail");
return NULL;
}
node->data = x;
node->left = NULL;
node->right = NULL;
return node;
}
void TreeDestroy(BTNode* root)
{
if (root == NULL) return;
TreeDestroy(root->left);
TreeDestroy(root->right);
free(root);
}
void PreOrder(BTNode* root)
{
if (root == NULL) {
printf("NULL ");
return;
}
printf("%d ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
void InOrder(BTNode* root)
{
if (root == NULL) {
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->data);
InOrder(root->right);
}
void PostOrder(BTNode* root)
{
if (root == NULL) {
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->data);
}
int TreeSize(BTNode* root)
{
return root == NULL ? 0 :
TreeSize(root->left)
+ TreeSize(root->right)
+ 1;
}
int TreeHeight(BTNode* root)
{
if (root == NULL) return 0;
int leftHeight = TreeHeight(root->left);
int rightHeight = TreeHeight(root->right);
return leftHeight > rightHeight ?
leftHeight + 1 : rightHeight + 1;
}
int TreeLevelKSize(BTNode* root, int k)
{
assert(k > 0);
if (root == NULL) return 0;
if (k == 1) return 1;
return TreeLevelKSize(root->left, k - 1)
+ TreeLevelKSize(root->right, k - 1);
}
BTNode* TreeFind(BTNode* root, BTDataType x)
{
if (root == NULL) return NULL;
if (root->data == x) return root;
BTNode* lret = TreeFind(root->left, x);
if (lret) return lret;
BTNode* rret = TreeFind(root->right, x);
if (rret) return rret;
return NULL;
}
void LevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root) QueuePush(&q, root);
while (!QueueEmpty(&q)) {
BTNode* front = QueueFront(&q);
QueuePop(&q);
printf("%d ", front->data);
if (front->left) {
QueuePush(&q, front->left);
}
if (front->right) {
QueuePush(&q, front->right);
}
}
QueueDestroy(&q);
}
bool TreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root) QueuePush(&q, root);
while (!QueueEmpty(&q)) {
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front == NULL) {
break;
} else {
QueuePush(&q, front->left);
QueuePush(&q, front->right);
}
}
// 开始判断是否是完全二叉树
while (!QueueEmpty(&q)) {
BTNode* front = QueueFront(&q);
QueuePop(&q);
// 出现非空节点, 说明非空节点不连续
if (front) {
QueueDestroy(&q);
return false;
}
}
QueueDestroy(&q);
return true;
}