文章目录
二叉树的实现
//#include "BinaryTree.h"
#pragma once
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
typedef char BTDataType;
typedef struct BinaryTreeNode
{
BTDataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
}BTNode;
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode** proot);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);
二叉树的遍历
前序遍历:根→左子树→右子树
中序遍历:左子树→根→右子树
后序遍历:左子树→右子树→根
前序遍历、中序遍历、后序遍历 三者中,除 前序+后序(都只能确定根) 以外,每两两组合可以确定唯一的树
层序遍历:一层一层遍历,从左到右
二叉树结点的个数
- int size 统计个数?→ 函数中定义的局部变量出函数作用域就会被销毁
- 定义静态/全局变量?→ 多次调用函数就会累计计算,每次使用之后变量需要被置零;静态变量无法置零;
- 这里选择用 递归:树的结点个数 = root + root的左子树 + root的右子树
// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
if (!root)
{
return 0;
}
return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
//上述代码可以简化
//(如果……)?(就……):(否则就……)👇
//(简化:return root==NULL ? 0 : BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}
二叉树叶子结点的个数:“不加自己”
- 是 空 吗?是就return 0
- 是 叶结点 吗?是就return 1
- 以上都不是?return 左数叶结点的个数+右数叶结点的个数
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (!root)
{
return 0;
}
if ((root->_left == NULL) && (root->_right == NULL))
{
return 1;
}
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
二叉树第k层的结点个数
- 第k层 = 第1层往下的第 (k-0) 层 = 第 2 层往下的第 (k-1) 层 = …… = 第k层的(k-(k-1))层 = 第k层的第1层
则有 (root,k)= (root->left, k-1)+(root->right, k-1) 依次递归。
首先判断若 root为NULL则return 0. 若走到“第1层”如下图,return1
二叉树查找值为x的结点
以参数 root 为根结点往下找
- 首先 “自查”:
- 该结点 是否为空 ? ⇢ 为空
return NULL
- ↓
- 不为空
- 该节点 是否为要查找的结点 ? ⇢ 是,
return 该结点
- ↓
- 不是
- 查找 左子树
- 以 root->left 为 根结点往下找 重复上述 自查过程
- 最终 层层递归 ⇢ 找到
return 某个结点
- ↓
- 一直找到NULL都没找到 ⇢
return NULL
- 查找 右子树
- 以 root->right 为 根结点往下找 重复上述 自查过程
- 找到 ⇢
return 某个结点
- 一直找到NULL都没找到 ⇢
return NULL
- 该结点 是否为空 ? ⇢ 为空
下面这个代码中定义两个变量存储结果的必要性
> BTNode* left = BinaryTreeFind(root->_left, x);
> BTNode* right =BinaryTreeFind(root->_right, x);
**这里为了判断层层递归调用函数之后得到结果就判断了一下,没有把结果储存起来,return的时候又重新递归调用函数取找这个未被储存的结果**
if (BinaryTreeFind(root->_left, x);
return BinaryTreeFind(root->_left, x);
if (BinaryTreeFind(root->_right, x)
return right;
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (!root)
return NULL;
if (root->_data == x)
return root;
BTNode* left = BinaryTreeFind(root->_left, x);
if (left)
return left;
BTNode* right = BinaryTreeFind(root->_right, x);
if (right)
return right;
return NULL;
}
函数接口实现-完整代码
#include "BinaryTree.h"
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int* pi)
{
assert(a);
if (a[*pi] == '#')
{
++(*pi);
return NULL;
}
BTNode* root = NULL;
BTNode* tmp = (BTNode*)malloc(sizeof(BTNode));
if (!tmp)
{
perror("malloc fail");
exit(-1);
}
tmp->_left = tmp->_right = NULL;
root = tmp;
root->_data = a[*pi];
++(*pi);
root->_left = BinaryTreeCreate(a, pi);
root->_right = BinaryTreeCreate(a, pi);
return root;
}
// 二叉树销毁
void BinaryTreeDestory(BTNode** proot)
{
if ((*proot) != NULL)
{
BTNode* left = (*proot)->_left;
BTNode* right = (*proot)->_right;
free(*proot);
*proot = NULL;
BinaryTreeDestory(&left);
BinaryTreeDestory(&right);
}
}
// 二叉树节点个数
int BinaryTreeSize(BTNode* root)
{
if (!root)
{
return 0;
}
return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
}
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (!root)
{
return 0;
}
if ((root->_left == NULL) && (root->_right == NULL))
{
return 1;
}
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
if (!root)
return 0;
if (k == 1)
return 1;
k--;
return BinaryTreeLevelKSize(root->_left, k) + BinaryTreeLevelKSize(root->_right, k);
}
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (!root)
return NULL;
if (root->_data == x)
return root;
BTNode* left = BinaryTreeFind(root->_left, x);
if (left)
return left;
BTNode* right = BinaryTreeFind(root->_right, x);
if (right)
return right;
return NULL;
}
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
if (!root)
{
printf("# ");
return;
}
printf("%c ", root->_data);
BinaryTreePrevOrder(root->_left);
BinaryTreePrevOrder(root->_right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
if (!root)
{
printf("# ");
return;
}
BinaryTreeInOrder(root->_left);
printf("%c ", root->_data);
BinaryTreeInOrder(root->_right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
if (!root)
{
printf("# ");
return;
}
BinaryTreePostOrder(root->_left);
BinaryTreePostOrder(root->_right);
printf("%c ", root->_data);
}
// 层序遍历
#include "Queue.h"
void BinaryTreeLevelOrder(BTNode* root)
{
Queue q;
QueueInit(&q);
if (root)
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
QDataType front = QueueFront(&q);
printf("%c ", front->_data);
QueuePop(&q);//出一层
//带下一层
if (front->_left)
QueuePush(&q, front->_left);
if (front->_right)
QueuePush(&q, front->_right);
}
QueueDestroy(&q);
}
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)
{
assert(root);
//层序遍历,如果访问到NULL后面还有数据就不是完全二叉树
Queue q;
QueueInit(&q);
if (root)
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
QDataType front = QueueFront(&q);
QueuePop(&q);//出一层
if (!front)//队头遇到NULL跳出循环
{
break;
}
else
{
//带下一层(不管是不是空,都先把下一层房间去)
QueuePush(&q, front->_left);
QueuePush(&q, front->_right);
}
}
while (!QueueEmpty(&q))
{
QDataType front = QueueFront(&q);
QueuePop(&q);//出一层
if (!front)
{
QueueDestroy(&q);
return 0;
}
}
QueueDestroy(&q);
return 1;
}