【数据结构】二叉树(2)

ops/2024/11/28 20:52:52/

目录

1. 二叉树的遍历

前序遍历

中序遍历

后序遍历

2. 计算二叉树中的节点个数

3. 计算二叉树中叶子节点个数

4. 计算二叉树的深度

5. 计算二叉树第k层节点个数

6. 二叉树基础练习

7. 二叉树的创建

8. 二叉树的销毁

9. 层序遍历

10. 判断二叉树是否为完全二叉树


1. 二叉树的遍历

二叉树遍历(traversal)是按照一定的次序访问二叉树中的所有节点,并且每个节点仅被访问一次的过程。它是二叉树最基本的运算,是二叉树中所有其他运算实现的基础。

  1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
  2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
  3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。

前序遍历递归图解:

代码实现

前序遍历

//前序遍历
void PrevOrder(BTNode* root)
{if (root == NULL){printf("空 ");return;}printf("%d ", root->data);PrevOrder(root->left);PrevOrder(root->right);
}

中序遍历

//中序遍历
void InOrder(BTNode* root)
{if (root == NULL){printf("空 ");return;}	InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}

后序遍历

//后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf("空 ");return;}PostOrder(root->left);	PostOrder(root->right);printf("%d ", root->data);
}

以中序遍历为例,递归展开图: 

代码实现: 

#include<stdio.h>
#include<stdlib.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{BTDataType data;//数据元素struct BinaryTreeNode* left;//指向左孩子struct BinaryTreeNode* right;//指向右孩子
}BTNode;BTNode* BuyNodee(int 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;
}//创建二叉树
BTNode* CreateBinaryTree()
{BTNode* node1 = BuyNodee(1);BTNode* node2 = BuyNodee(2);BTNode* node3 = BuyNodee(3);BTNode* node4 = BuyNodee(4);BTNode* node5 = BuyNodee(5);BTNode* node6 = BuyNodee(6);BTNode* node7 = BuyNodee(7);node1->left = node2;node1->right = node4;node2->left = node3;node4->left = node5;node4->right = node6;return node1;
}//前序遍历
void PrevOrder(BTNode* root)
{if (root == NULL){printf("空 ");return;}printf("%d ", root->data);PrevOrder(root->left);PrevOrder(root->right);
}//中序遍历
void InOrder(BTNode* root)
{if (root == NULL){printf("空 ");return;}	InOrder(root->left);printf("%d ", root->data);InOrder(root->right);
}//后序遍历
void PostOrder(BTNode* root)
{if (root == NULL){printf("空 ");return;}PostOrder(root->left);	PostOrder(root->right);printf("%d ", root->data);
}int main()
{BTNode* root = CreateBinaryTree();//前序遍历PrevOrder(root);printf("\n");//中序遍历InOrder(root);printf("\n");//后序遍历PostOrder(root);printf("\n");return 0;
}

运行结果:

2. 计算二叉树中的节点个数

递归思想:

如果二叉树为空,节点个数为0。

如果二叉树不为空,二叉树节点个数=左子树节点个数 + 右子树节点个数 +1

代码实现:

//节点个数
int TreeSize(BTNode* root)
{return root == NULL ? 0 :TreeSize(root->left) + TreeSize(root->right) + 1;
}

3. 计算二叉树中叶子节点个数

递归思想:

如果二叉树为空,返回0。

如果二叉树不为空,左右子树为空,返回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);
}

4. 计算二叉树的深度

递归思想:

如果二叉树为空,二叉树的深度为0。

如果二叉树不为空,二叉树的深度 = max(左子树深度,右子树深度)+1。 

代码实现: 

//二叉树的深度
int TreeHeight(BTNode* root)
{if (root == NULL)return 0;int height1 = TreeHeight(root->left);int height2 = TreeHeight(root->right);return height1 > height2 ? height1+1 : height2+1;
}

5. 计算二叉树第k层节点个数

递归思想:

如果二叉树为空,返回0。

如果二叉树不为空且k=1,返回1。

如果二叉树不为空且k>1,返回左子树中k-1层节点个数加右子树中k-1层节点个数。

代码实现:

//计算二叉树第k层节点个数
int TreeLevelKSize(BTNode* root,int k)
{if (root == NULL)return 0;if (k == 1)return 1;return TreeLevelKSize(root->left, k - 1)+ TreeLevelKSize(root->right, k - 1);
}

 在栈中大致过程

6. 二叉树基础练习

题目1 单植二叉树【链接】

题目2 相同的树【链接】

题目3 对称二叉树【链接】

题目4 二叉树的前序遍历【链接】

题目5 二叉树的中序遍历【链接】

题目6 二叉树的后序遍历【链接】

题目7 另一棵树的子树【链接】

7. 二叉树的创建

二叉树的构建及遍历【链接】

代码实现 :

#include <stdio.h>
typedef struct BinaryTreeNode
{struct BinaryTreeNode* left;struct BinaryTreeNode* right;char val;
}BTNode;BTNode* CreateTree(char*a,char*pi)
{if(a[(*pi)]=='#'){(*pi)++;return NULL;}   BTNode* root=(BTNode*)malloc(sizeof(BTNode));root->val=a[(*pi)++];root->left=CreateTree(a,pi);root->right=CreateTree(a,pi);return root;
}//中序遍历
void InOrder(BTNode* root)
{if (root == NULL){		return;}	InOrder(root->left);printf("%c ", root->val);InOrder(root->right);
}int main() 
{char a[100];scanf("%s",a);char i=0;BTNode* root=CreateTree(a,&i);InOrder(root);return 0;
}

8. 二叉树的销毁

代码实现:

//二叉树的销毁(后序遍历)
void TreeDestory(BTNode* root)
{if (root == NULL)return;TreeDestory(root->left);TreeDestory(root->right);free(root);
}

9. 层序遍历

从上到下,从左到右依次将每个数放入到队列中,然后按顺序依次打印就是想要的结果。
1、首先将二叉树的根节点push到队列中,判断队列不为NULL,就输出队头的元素。
2、判断节点是否有孩子,如果有就将孩子push到队列中。

代码实现:

由于要访问每个节点的左右孩子,所以队列的元素类型为节点的指针。Queue.h【链接】

#include"Queue.h"//层序遍历
void TreeLevelOrder(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);
}

10. 判断二叉树是否为完全二叉树

基本思想:

按照层序遍历,遇到空也进队列,出队列出到空时,就开始判断,后面是全空就是完全二叉树,后面有非空就不是完全二叉树。例:

//判断二叉树是否是完全二叉树
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;}QueuePush(&q, front->left);		QueuePush(&q, front->right);}while (!QueueEmpty(&q)){BTNode* front = QueueFront(&q);QueuePop(&q);if (front)//如果有非空,就不是完全二叉树{return false;}}QueueDesTroy(&q);return true;
}


http://www.ppmy.cn/ops/137468.html

相关文章

Linux 命令之 `man` 命令详解

在Linux系统中&#xff0c;man&#xff08;manual的缩写&#xff09;命令是一个非常重要的工具&#xff0c;用于查看命令的手册页&#xff08;manual pages&#xff09;。这些手册页包含了关于命令的详细描述、选项、用法示例和相关信息。本文将详细介绍man命令的使用方法和一些…

ts解决vite unplugin-auto-import/vite

vite-env.d.ts加入即可 /* eslint-disable */ /* prettier-ignore */ // ts-nocheck // noinspection JSUnusedGlobalSymbols // Generated by unplugin-auto-import export { } declare global {const EffectScope: typeof import(vue)[EffectScope]const acceptHMRUpdate: t…

Linux iptables 命令详解

简介 iptables 是一个在 Linux 中的管理防火墙规则的命令行工具&#xff0c;它作为 Linux 内核的 netfilter 框架的一部分运行&#xff0c;以控制传入和传出的网络流量。 与 firewalld 相比 iptables 是基于规则的&#xff0c;每个规则必须独立定义&#xff0c;firewalld 是基…

【Threejs进阶教程-着色器篇】9.顶点着色器入门

【Threejs进阶教程-着色器篇】9.顶点着色器入门 本系列教程第一篇地址&#xff0c;建议按顺序学习认识顶点着色器varying介绍顶点着色器与片元着色器分别的作用Threejs在Shader中的内置变量各种矩阵gl_Position 尝试使用顶点着色器增加分段数增强效果 制作平面鼓包效果鼓包效果…

笔记本外接4k显示器只有30Hz刷新率

方法 注意显示器设置里有一个调节帧率的选项是可以选60帧的&#xff0c;如果不能修改 通过按钮找到显示-USBC优先级&#xff0c;选择高分辨率&#xff0c;之后在显示器设置中应该出现60Hz的选项&#xff0c;更改选项则切换至60Hz 原因是USBC线缆存在高分辨率和高数据传输两种模…

Vue-TreeSelect组件最下级隐藏No sub-options

问题&#xff1a;最下级没有数据的话&#xff0c;去除No sub-options信息 为什么没下级&#xff0c;会展示这个&#xff1f; 整个树形结构数据都是由后端构造好返回给前端的。默认子类没数据的话&#xff0c;children是一个空数组。也就是因为这最下级的空数组&#xff0c;导致…

scala模式匹配

object test47 {def main(args: Array[String]): Unit {val id"445646546548858548648"//取出id前两位val provinceid.substring(0,2) // println(province) // if (province"42"){ // println("湖北") // }else if(province&quo…

结构方程模型(SEM)入门到精通:lavaan VS piecewiseSEM、全局估计/局域估计;潜变量分析、复合变量分析、贝叶斯SEM在生态学领域应用

目录 第一章 夯实基础 R/Rstudio简介及入门 第二章 结构方程模型&#xff08;SEM&#xff09;介绍 第三章 R语言SEM分析入门&#xff1a;lavaan VS piecewiseSEM 第四章 SEM全局估计&#xff08;lavaan&#xff09;在生态学领域高阶应用 第五章 SEM潜变量分析在生态学领域…