👀个人简介:一个正在努力奋斗逆天改命的二本觉悟生
前言:通过上篇博客的学习,我们实现了二叉树的前中后序遍历,体验到了递归的暴力美学,这篇博客将带着大家实现二叉树的接口
目录
一、求二叉树节点个数
在正式开始之前我们先把上次写的代码里的test.c中创建树的代码优化一下,这样方便后续操作
#include"Tree.h"
BTNode* buyNode(char x)
{
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
newnode->data = x;
newnode->left = newnode->right = NULL;
return newnode;
}
BTNode* CreateTree()
{
BTNode* nodeA = buyNode('A');
BTNode* nodeB = buyNode('B');
BTNode* nodeC = buyNode('C');
BTNode* nodeD = buyNode('D');
BTNode* nodeE = buyNode('E');
BTNode* nodeF = buyNode('F');
nodeA->left = nodeB;
nodeA->right = nodeC;
nodeB->left = nodeD;
nodeC->left = nodeE;
nodeC->right = nodeF;
return nodeA;
}
void test1()
{
BTNode* root = CreateTree();
//前中后序遍历
//PreOrder(root);
//InOrder(root);
//PostOrder(root);
}
int main()
{
test1();
return 0;
}
二叉树节点个数=根节点+左子树节点个数+右子树节点个数
代码实现:
//方法三:节点总数=1+左子树节点个数+右子树节点个数
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
如图:
test.c:
#include"Tree.h"
BTNode* buyNode(char x)
{
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
newnode->data = x;
newnode->left = newnode->right = NULL;
return newnode;
}
BTNode* CreateTree()
{
BTNode* nodeA = buyNode('A');
BTNode* nodeB = buyNode('B');
BTNode* nodeC = buyNode('C');
BTNode* nodeD = buyNode('D');
BTNode* nodeE = buyNode('E');
BTNode* nodeF = buyNode('F');
nodeA->left = nodeB;
nodeA->right = nodeC;
nodeB->left = nodeD;
nodeC->left = nodeE;
nodeC->right = nodeF;
return nodeA;
}
void test1()
{
BTNode* root = CreateTree();
//前中后序遍历
//PreOrder(root);
//InOrder(root);
//PostOrder(root);
//二叉树结点个数
printf("Size: %d\n", BinaryTreeSize(root));
}
int main()
{
test1();
return 0;
}
测试结果:
测试结果正确,程序退出码为0
二.求二叉树叶子节点个数
叶子节点:左右孩子都为空的节点
二叉树叶子节点个数=左子树叶子节点个数+右子树叶子节点个数
代码实现:
// ⼆叉树叶⼦结点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
如图:
test.c:
#include"Tree.h"
BTNode* buyNode(char x)
{
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
newnode->data = x;
newnode->left = newnode->right = NULL;
return newnode;
}
BTNode* CreateTree()
{
BTNode* nodeA = buyNode('A');
BTNode* nodeB = buyNode('B');
BTNode* nodeC = buyNode('C');
BTNode* nodeD = buyNode('D');
BTNode* nodeE = buyNode('E');
BTNode* nodeF = buyNode('F');
nodeA->left = nodeB;
nodeA->right = nodeC;
nodeB->left = nodeD;
nodeC->left = nodeE;
nodeC->right = nodeF;
return nodeA;
}
void test1()
{
BTNode* root = CreateTree();
//前中后序遍历
//PreOrder(root);
//InOrder(root);
//PostOrder(root);
//二叉树结点个数
//printf("Size: %d\n", BinaryTreeSize(root));
//二叉树叶子结点个数
printf("LeafSize: %d\n", BinaryTreeLeafSize(root));
}
int main()
{
test1();
return 0;
}
测试结果:
测试结果正确,程序退出码为0
三.求二叉树第k层节点个数
当k==1时当前节点就是第k层节点
二叉树第k层节点个数=左子树第k-1层节点个数+右子树第k-1层节点个数
代码实现:
// ⼆叉树第k层结点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinaryTreeLevelKSize(root->left, k - 1)
+ BinaryTreeLevelKSize(root->right, k - 1);
}
如图:
test.c:
#include"Tree.h"
BTNode* buyNode(char x)
{
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
newnode->data = x;
newnode->left = newnode->right = NULL;
return newnode;
}
BTNode* CreateTree()
{
BTNode* nodeA = buyNode('A');
BTNode* nodeB = buyNode('B');
BTNode* nodeC = buyNode('C');
BTNode* nodeD = buyNode('D');
BTNode* nodeE = buyNode('E');
BTNode* nodeF = buyNode('F');
nodeA->left = nodeB;
nodeA->right = nodeC;
nodeB->left = nodeD;
nodeC->left = nodeE;
nodeC->right = nodeF;
return nodeA;
}
void test1()
{
BTNode* root = CreateTree();
//前中后序遍历
//PreOrder(root);
//InOrder(root);
//PostOrder(root);
//二叉树结点个数
//printf("Size: %d\n", BinaryTreeSize(root));
//二叉树叶子结点个数
//printf("LeafSize: %d\n", BinaryTreeLeafSize(root));
//第k层节点个数
printf("K Size: %d\n", BinaryTreeLevelKSize(root,3));
}
int main()
{
test1();
return 0;
}
测试结果:
测试结果正确,程序退出码为0
四.求二叉树的深度/高度
二叉树的高度=根节点+max(左子树的高度,右子树的高度)
代码实现:
//⼆叉树的深度/⾼度
int BinaryTreeDepth(BTNode* root)
{
if (root == NULL)
{
return 0;
}
//根节点+MAX(左子树高度,右子树高度)
int leftDep = BinaryTreeDepth(root->left);
int rightDep = BinaryTreeDepth(root->right);
return 1 + (leftDep > rightDep ? leftDep : rightDep);
}
如图:
test.c:
#include"Tree.h"
BTNode* buyNode(char x)
{
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
newnode->data = x;
newnode->left = newnode->right = NULL;
return newnode;
}
BTNode* CreateTree()
{
BTNode* nodeA = buyNode('A');
BTNode* nodeB = buyNode('B');
BTNode* nodeC = buyNode('C');
BTNode* nodeD = buyNode('D');
BTNode* nodeE = buyNode('E');
BTNode* nodeF = buyNode('F');
nodeA->left = nodeB;
nodeA->right = nodeC;
nodeB->left = nodeD;
nodeC->left = nodeE;
nodeC->right = nodeF;
return nodeA;
}
void test1()
{
BTNode* root = CreateTree();
//前中后序遍历
//PreOrder(root);
//InOrder(root);
//PostOrder(root);
//二叉树结点个数
//printf("Size: %d\n", BinaryTreeSize(root));
//二叉树叶子结点个数
//printf("LeafSize: %d\n", BinaryTreeLeafSize(root));
//第k层节点个数
//printf("K Size: %d\n", BinaryTreeLevelKSize(root,3));
//二叉树的深度/高度
printf("Depth: %d\n", BinaryTreeDepth(root));
}
int main()
{
test1();
return 0;
}
测试结果:
测试结果正确,程序退出码为0
五.二叉树查找值为x的节点
递归查找,找到了就返回当前节点,如果是在左子树中找到就直接返回,没找到继续来到右子树找,最好都没找到就返回NULL
代码实现:
// ⼆叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BTNode* leftFind = BinaryTreeFind(root->left,x);
if (leftFind)
{
return leftFind;
}
BTNode* rightFind = BinaryTreeFind(root->right, x);
if (rightFind)
{
return rightFind;
}
return NULL;
}
如图:
test.c:
#include"Tree.h"
BTNode* buyNode(char x)
{
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
newnode->data = x;
newnode->left = newnode->right = NULL;
return newnode;
}
BTNode* CreateTree()
{
BTNode* nodeA = buyNode('A');
BTNode* nodeB = buyNode('B');
BTNode* nodeC = buyNode('C');
BTNode* nodeD = buyNode('D');
BTNode* nodeE = buyNode('E');
BTNode* nodeF = buyNode('F');
nodeA->left = nodeB;
nodeA->right = nodeC;
nodeB->left = nodeD;
nodeC->left = nodeE;
nodeC->right = nodeF;
return nodeA;
}
void test1()
{
BTNode* root = CreateTree();
//前中后序遍历
//PreOrder(root);
//InOrder(root);
//PostOrder(root);
//二叉树结点个数
//printf("Size: %d\n", BinaryTreeSize(root));
//二叉树叶子结点个数
//printf("LeafSize: %d\n", BinaryTreeLeafSize(root));
//第k层节点个数
//printf("K Size: %d\n", BinaryTreeLevelKSize(root,3));
//二叉树的深度/高度
//printf("Depth: %d\n", BinaryTreeDepth(root));
//二叉树查找值为x的结点
BTNode* pos = BinaryTreeFind(root, 'E');
if (pos)
{
printf("找到了\n");
}
else {
printf("没找到\n");
}
}
int main()
{
test1();
return 0;
}
测试结果:
测试结果正确,程序退出码为0
六.二叉树的销毁
--由于提前释放根节点会导致找不到左右子树,所以销毁操作我们要模仿后序遍历,还有这里得传地址,后续的使用也需要注意一下写法。
// ⼆叉树销毁
void BinaryTreeDestory(BTNode** root)
{
if (*root == NULL)
{
return;
}
BinaryTreeDestory(&(*root)->left);
BinaryTreeDestory(&(*root)->right);
free(*root);
*root = NULL;
}
如图:
七、代码展现
Tree.h:
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef char BTDataType;
typedef struct BinaryNode
{
BTDataType data;
struct BinaryNode* left;//左孩子
struct BinaryNode* right;//右孩子
}BTNode;
//前序遍历
void PreOrder(BTNode* root);
//中序遍历
void InOrder(BTNode* root);
//后序遍历
void PostOrder(BTNode* root);
// 二叉树结点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子结点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层结点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
//二叉树的深度/高度
int BinaryTreeDepth(BTNode* root);
// 二叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
Tree.c:
#include"Tree.h"
//前序遍历
void PreOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
//根左右
printf("%c ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
//中序遍历
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
//左根右
InOrder(root->left);
printf("%c ", root->data);
InOrder(root->right);
}
//后序遍历
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
//左右根
PostOrder(root->left);
PostOrder(root->right);
printf("%c ", root->data);
}
// 二叉树结点个数=根节点+左子树节点个数+右子树节点个数
int BinaryTreeSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}
// 二叉树叶子结点个数=左子树叶子节点个数+右子树节点个数
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
//判断是否为叶子节点(没有左右孩子)
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
// 二叉树第k层节点个数=左子树第K-1层节点个数+右子树第k-1层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k)
{
if (root == NULL)
{
return 0;
}
//判断是否为第k层
if (k == 1)
{
return 1;
}
//每次注意要k-1
return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}
//二叉树的深度/高度=根节点+max(左子树高度,右子树高度)
int BinaryTreeDepth(BTNode* root)
{
if (root == NULL)
{
return 0;
}
int leftdepth = BinaryTreeDepth(root->left);
int rightdepth = BinaryTreeDepth(root->right);
return 1 + (leftdepth > rightdepth ? leftdepth : rightdepth);
}
// 二叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
{
return NULL;
}
if (root->data == x)
{
return root;
}
BTNode*leftroot = BinaryTreeFind(root->left, x);
//如果leftroot不为空就是找到了直接返回
if (leftroot)
{
return leftroot;
}
//没找到就继续右子树找
BTNode* rightroot = BinaryTreeFind(root->right, x);
if (rightroot)
{
return rightroot;
}
//都没找到就返回空
return NULL;
}
// 二叉树销毁--采用后序遍历的思想
void BinaryTreeDestory(BTNode** root)
{
if (*root == NULL)
{
return;
}
BinaryTreeDestory(&(*root)->left);
BinaryTreeDestory(&(*root)->right);
free(*root);
*root = NULL;
}
test.c:
#include"Tree.h"
BTNode* buyNode(char x)
{
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
newnode->data = x;
newnode->left = newnode->right = NULL;
return newnode;
}
BTNode* CreateTree()
{
BTNode* nodeA = buyNode('A');
BTNode* nodeB = buyNode('B');
BTNode* nodeC = buyNode('C');
BTNode* nodeD = buyNode('D');
BTNode* nodeE = buyNode('E');
BTNode* nodeF = buyNode('F');
nodeA->left = nodeB;
nodeA->right = nodeC;
nodeB->left = nodeD;
nodeC->left = nodeE;
nodeC->right = nodeF;
return nodeA;
}
void test1()
{
BTNode* root = CreateTree();
//前中后序遍历
//PreOrder(root);
//InOrder(root);
//PostOrder(root);
//二叉树结点个数
printf("Size: %d\n", BinaryTreeSize(root));
//二叉树叶子结点个数
printf("LeafSize: %d\n", BinaryTreeLeafSize(root));
//第k层节点个数
printf("K Size: %d\n", BinaryTreeLevelKSize(root,3));
//二叉树的深度/高度
printf("Depth: %d\n", BinaryTreeDepth(root));
//二叉树查找值为x的结点
BTNode* pos = BinaryTreeFind(root, 'E');
if (pos)
{
printf("找到了\n");
}
else {
printf("没找到\n");
}
// 二叉树销毁
BinaryTreeDestory(&root);
}
int main()
{
test1();
return 0;
}
往期回顾:
总结:这篇博客就把二叉树的部分接口实现了,后续还有i一个层序遍历和判断是否为完全二叉树,将在下篇博客给大家展现,如果文章对你有帮助的话,欢迎评论,点赞,收藏加关注,感谢大家的支持。