实现二叉树
文章目录
前言
普通二叉树的增删改查没有什么意义,但掌握普通二叉树的实现对递归的掌握和后续学习AVL树、红黑树等有很大帮助。
1. 二叉树节点定义
typedef char DataType;
typedef struct BinaryTreeNode
{
DataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
}Node;
2. 二叉树的接口
// 通过前序遍历的字符串"ABD##E#H##CF##G##" 重构二叉树
//前序 ABD##E#H##CF##G##
//中序 #D#B#E#H#A#F#C#G#
Node* BinaryTreeCreate(DataType* a, int* pi);
// 销毁
void BinaryTreeDestory(Node* root);
// 节点个数
int BinaryTreeSize(Node* root);
// 叶子节点个数
int BinaryTreeLeafSize(Node* root);
// 第k层节点个数
int BinaryTreeLevelKSize(Node* root, int k);
// 查找值为x的节点
Node* BinaryTreeFind(Node* root, DataType x);
// 前序遍历
void BinaryTreePrevOrder(Node* root);
// 中序遍历
void BinaryTreeInOrder(Node* root);
// 后序遍历
void BinaryTreePostOrder(Node* root);
// 层序遍历
void BinaryTreeLevelOrder(Node* root);
// 是否是完全二叉树
bool BinaryTreeComplete(Node* root);
// 返回二叉树高度
int BinaryTreeDepth(Node* root);
3. 接口实现
3.1 创建二叉树
// 通过前序遍历的字符数组"ABD##E#H##CF##G##"构建二叉树
Node* BinaryTreeCreate(DataType* arr, int* pi)
{
if (arr[*pi] == '#')
{
(*pi)++;
return NULL;
}
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode)
{
printf("malloc fail\n");
exit(-1);
}
newNode->_data = arr[(*pi)++];
newNode->_left = BinaryTreeCreate(arr, pi);
newNode->_right = BinaryTreeCreate(arr, pi);
return newNode;
}
3.2 销毁二叉树
// 二叉树销毁
// 通过后续遍历销毁二叉树
void BinaryTreeDestory(Node* root)
{
if (!root)
return;
BinaryTreeDestory(root->_left);
BinaryTreeDestory(root->_right);
free(root);
}
3.3 二叉树高度
// 思路:depth = 根节点高度 + max(左子树高度,右子树高度)
int BinaryTreeDepth(Node* root)
{
if (!root)
return 0;
int left = BinaryTreeDepth(root->_left);
int right = BinaryTreeDepth(root->_right);
return left > right ? 1 + left : right + 1;
}
3.4二叉树节点个数
int BinaryTreeSize(Node* root)
{
return !root ? 0 : 1
+ BinaryTreeSize(root->_left)
+ BinaryTreeSize(root->_right);
}
3.4 二叉树叶子节点个数
// 二叉树叶子节点个数
int BinaryTreeLeafSize(Node* root)
{
if (!root)
return 0;
if (root->_left == NULL && root->_right == NULL)
return 1;
return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}
3.5 二叉树第k层节点个数
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(Node* root, int k)
{
if (!root)
return 0;
if (k == 1)
return 1;
return BinaryTreeLevelKSize(root->_left, k - 1)
+ BinaryTreeLevelKSize(root->_right, k - 1);
}
3.6 查找值为x的节点
// 二叉树查找值为x的节点
Node* BinaryTreeFind(Node* root, DataType x)
{
if (!root)
return NULL;
if (root->_data == x)
return root;
return BinaryTreeFind(root->_left, x) ||
BinaryTreeFind(root->_right, x);
}
3.7 前、中、后序遍历
// 二叉树前序遍历
void BinaryTreePrevOrder(Node* root)
{
if (!root)
{
printf("# ");
return;
}
printf("%c ", root->_data);
BinaryTreePrevOrder(root->_left);
BinaryTreePrevOrder(root->_right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(Node* root)
{
if (!root)
{
printf("# ");
return;
}
BinaryTreeInOrder(root->_left);
printf("%c ", root->_data);
BinaryTreeInOrder(root->_right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(Node* root)
{
if (!root)
{
printf("# ");
return;
}
BinaryTreePostOrder(root->_left);
BinaryTreePostOrder(root->_right);
printf("%c ", root->_data);
}
3.8 层序遍历
// 层序遍历
// ABD##E#H##CF##G##
// 借助队列实现
void BinaryTreeLevelOrder(Node* root)
{
int depth = BinaryTreeDepth(root);
Node** que = (Node*)malloc(sizeof(Node*) * (int)pow(2, depth));
int head = -1;
int tail = -1;
que[++tail] = root;
while (head < tail)
{
printf("%c ", que[++head]->_data);
if (que[head]->_left)
que[++tail] = que[head]->_left;
if (que[head]->_right)
que[++tail] = que[head]->_right;
}
free(que);
}
3.9 判断是否完全二叉树
// 判断二叉树是否是完全二叉树
// 完全二叉树 ABD##E##CF##G##
bool BinaryTreeComplete(Node* root)
{
if (!root) return false;
int depth = BinaryTreeDepth(root);
int newDepth = depth + 1;
Node** que = (Node*)malloc(sizeof(Node*) * (int)pow(2, newDepth));
int head = -1;
int tail = -1;
que[++tail] = root;
while (head < tail)
{
head++;
if (que[head] == NULL)
break;
que[++tail] = que[head]->_left;
que[++tail] = que[head]->_right;
}
while (head < tail)
{
if (que[head] != NULL)
return false;
head++;
}
free(que);
return true;
}
4 测试
通过控制台输入此二叉树的前序遍历 。
代码示例:
#include "BinaryTree.h"
void test1()
{
char arr[100];
scanf("%s", arr);
//创建二叉树
int i = 0;
Node* root = BinaryTreeCreate(arr, &i);
printf("二叉树节点总数为:%d\n", BinaryTreeSize(root));
printf("二叉树叶子节点总数为:%d\n", BinaryTreeLeafSize(root));
int k = 3;
printf("二叉树第%d层节点总数为:%d\n", k, BinaryTreeLevelKSize(root, k));
printf("二叉树深度为:%d\n", BinaryTreeDepth(root));
if (BinaryTreeComplete(root))
printf("是完全二叉树\n");
else
printf("不是完全二叉树\n");
char c = 'A';
Node* find = BinaryTreeFind(root,c);
if (find)
printf("找到了\n");
else
printf("没找到\n");
//中序遍历
printf("中序遍历: ");
BinaryTreeInOrder(root);
printf("\n");
//层序遍历
printf("层序遍历: ");
BinaryTreeLevelOrder(root);
printf("\n");
BinaryTreeDestory(root);
root = NULL;
}
int main()
{
test1();
}
输出: