二叉链的表示
🎤二叉链也叫左右孩子表示法。 其中一个指针指向左孩子,另一个指针指向右孩子。
typedef char BTDataType;
typedef struct BinaryTreeNode
{
struct BinaryTreeNode\* left;//左孩子
struct BinaryTreeNode\* right;//右孩子
BTDataType data;
}BTNode;
二叉树的遍历(前中后序)
🎤遍历二叉树,即按照某条搜索路径巡防树中的每个结点,使每个结点有且仅被访问一次。 二叉树的链式结构一般都是用左右孩子表示法来实现,再由二叉树的定义可得,二叉树是由三个基本单元组成的,分别为根节点,左子树和右子树。
若限定先左和先右的话,就有三种情况:前序(先根)遍历;中序(中根)遍历;后序(后根)遍历。 由递归的思想可以,前中后序的操作定义也基本有了一定的思路:
- 前序遍历的思路:(1)先访问根结点;(2)前序遍历左子树;(3)前序遍历右子树。
void PrevOrder(BTNode\* root)//前序
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%c ", root->data);
PrevOrder(root->left);
PrevOrder(root->right);
}
- 中序遍历的思路:(1)先中序遍历左子树;(2)访问根结点;(3)中序遍历右子树。
void InOrder(BTNode\* root)//中序
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%c ", root->data);
InOrder(root->right);
}
- 后序遍历的思路:(1)先后序遍历左子树;(2)后序遍历右子树;(3)访问根结点。
void PostOrder(BTNode\* root)//后序
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%c ", root->data);
}
树结点的个数
🎤分治思想,将大问题分成小问题解决,在二叉树里就是递归的思想
int TreeSize(BTNode\* root)
{
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
叶子结点的个数
🎤度为0的结点被称为叶子或终端结点
int TreeLeafSize(BTNode\* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
层序遍历
🎤这里需要用到队列,最后我会把所有代码放在下面
🎤层序遍历的核心思想就是上一层出队的时候带着下一层所有的结点进队
//层序遍历,核心思想:上一层出队的时候带下一层的结点进队
void LevelOrder(BTNode\* root)
{
Queue q;
QueueInit(&q);
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
BTNode\* front = QueueFront(&q);
QueuePop(&q);
printf("%c ", front->data);
if (root->left)
{
QueuePush(&q, front->left);
}
if (root->right)
{
QueuePush(&q, front->right);
}
}
printf("\n");
QueueDestory(&q);
}
二叉树的销毁
🎤如果我们用前序或者中序来遍历销毁的话,会发现,有的结点找不到了,而后续遍历销毁却避开这个问题。
void TreeDestory(BTNode\* root)
{
if (root == NULL)
{
return;
}
TreeDestory(root->left);
TreeDestory(root->right);
free(root);
root = NULL;
}
代码
因为我们层序遍历中,用到了队,我就直接把队列的定义和实现的代码放了进来。 到这里,我相信大家对二叉树已经掌握了🎉🎉🎉,有错误大家可以指出哦,有疑问也可以问我,大家共同进步,后续会持续更新《数据结构》的相关内容,大家喜欢的话可以关注一下,😚😚😚下面是项目代码,大家参考一下。****
test.c
#include<stdio.h>
#include<stdlib.h>
#include"Queue.h"
typedef char BTDataType;
typedef struct BinaryTreeNode
{
struct BinaryTreeNode\* left;//左孩子
struct BinaryTreeNode\* right;//右孩子
BTDataType data;
}BTNode;
void PrevOrder(BTNode\* root)//前序
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%c ", root->data);
PrevOrder(root->left);
PrevOrder(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 TreeSize(BTNode\* root)
{
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
//求叶子结点的个数
int TreeLeafSize(BTNode\* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}
//层序遍历,核心思想:上一层出队的时候带下一层的结点进队
void LevelOrder(BTNode\* root)
{
Queue q;
QueueInit(&q);
if (root)
{
QueuePush(&q, root);
}
while (!QueueEmpty(&q))
{
BTNode\* front = QueueFront(&q);
QueuePop(&q);
printf("%c ", front->data);
if (root->left)
{
QueuePush(&q, front->left);
}
if (root->right)
{
QueuePush(&q, front->right);
}
}
printf("\n");
QueueDestory(&q);
}
//树的销毁--用后序的思想,一步一步销毁就行了
void TreeDestory(BTNode\* root)
{
if (root == NULL)
{
return;
}
TreeDestory(root->left);
TreeDestory(root->right);
free(root);
root = NULL;
}
int main()
{
BTNode\* A = (BTNode\*)malloc(sizeof(BTNode));
A->data = 'A';
A->left = NULL;
A->right = NULL;
BTNode\* B = (BTNode\*)malloc(sizeof(BTNode));
B->data = 'B';
B->left = NULL;
B->right = NULL;
BTNode\* C = (BTNode\*)malloc(sizeof(BTNode));
C->data = 'C';
C->left = NULL;
C->right = NULL;
BTNode\* D = (BTNode\*)malloc(sizeof(BTNode));
D->data = 'D';
D->left = NULL;
D->right = NULL;
BTNode\* E = (BTNode\*)malloc(sizeof(BTNode));
E->data = 'E';
E->left = NULL;
E->right = NULL;
//链接
A->left = B;
A->right = C;
B->left = D;
B->right = E;
PrevOrder(A);
printf("\n");
InOrder(A);
printf("\n");
PostOrder(A);
printf("\n");
printf("TreeSizeA:%d\n", TreeSize(A));
printf("TreeSizeB:%d\n", TreeSize(B));
printf("TreeLeafSizeA:%d\n", TreeLeafSize(A));
printf("TreeLeafSizeB:%d\n", TreeLeafSize(B));
LevelOrder(A);
TreeDestory(A);
return 0;
}
Queue.h
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.h>
//前置声明
struct BinaryTreeNode;
typedef struct BinaryTreeNode\* QDataType;
typedef struct QueueNode
{
struct QueueNode\* next;
QDataType data;
}QNode;
typedef struct Queue
{
QNode\* head;
QNode\* tail;
}Queue;
//初始化
void QueueInit(Queue\* pq);
//销毁
void QueueDestory(Queue\* pq);
//入队---队尾入
void QueuePush(Queue\* pq, QDataType x);
//出队---队头出
void QueuePop(Queue\* pq);
//取队头数据
QDataType QueueFront(Queue\* pq);
//取队尾数据
QDataType QueueBack(Queue\* pq);
//数据个数
int QueueSize(Queue\* pq);
//判空
bool QueueEmpty(Queue\* pq);
Queue.c
#include"Queue.h"
void QueueInit(Queue\* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
![img](https://img-blog.csdnimg.cn/img_convert/9ccd215ae86b3c8c8d451f225aee8f33.png)
![img](https://img-blog.csdnimg.cn/img_convert/4e578da7b930428df98e7a9048afbb50.png)
![img](https://img-blog.csdnimg.cn/img_convert/6efc8df0cc4454b8605028d355dbade3.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**
**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**
**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**
---
### Queue.c
#include"Queue.h"
void QueueInit(Queue* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
[外链图片转存中…(img-YKQ7h2rw-1714770488234)]
[外链图片转存中…(img-jBA6hADV-1714770488234)]
[外链图片转存中…(img-mtFcSP6y-1714770488234)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新