当前位置: 首页 > news >正文

数据结构之二叉树的定义及实现

1. 树的概念

主要的定义:
节点的度:一个节点含有的子树的个数称为该节点的度;如上图:A的为6

叶节点或终端节点:度为0的节点称为叶节点;如上图:B,C,H,I等节点为叶节点

分支节点或非终端节点:度不为0的节点;如上图:D,E,F,G等节点为分支节点

父节点或者双亲结点节点:若一个节点含有子节点,则这个节点成为其子节点的父节点

子节点或孩子节点:一个节点含有的子树的根节点称为该节点的子节点

兄弟节点:具有相同父节点的节点互称为兄弟节点

树的度:一棵树中最大节点的度称为树的度

节点的层次:从根开始定义起,根为第一层,根的子节点为第二层

树的高度或深度:树中结点的最大层次

节点的祖先:从根到该结点所经分支上的所有节点

子孙:以某节点为根的子树中任一节点都称为该节点的子孙

森林:由m(m>0)颗互不相交的多棵树的集合称为森林

2. 对各知识点的进一步画图解析:

  • 节点的度

  • 叶节点(终端节点)

  • 分支节点(非终端节点)

  • 父节点(双亲节点)

  • 子节点(孩子节点)

  • 兄弟节点

  • 树的高度

  • 节点的高度:从下往上数

  • 堂兄弟节点

  • 节点的祖先

  • 子孙

 3. 二叉树概念及结构

3.1概念

一棵二叉树是节点的有限集合,该集合或者为空,或者是由一个根节点加上两颗别称为左子树和右子树的二叉树组成。

3.2 二叉树的特点:

1. 每个节点最多有两颗子树,即二叉树不存在度大于2的节点。

2. 二叉树的子树有左右之分,其子树的次序不能颠倒。

3.3 链式二叉树存储的概念

二叉树的链式存储结构是指:用链表来表示一颗二叉树,即用链来指示元素的逻辑关系。

通常的方式是链表中每个节点由三个域组成,数据域和左右指针域,左右指针分别用来给出该节点左孩子和右孩子所在的链接点的存储地址。

链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链,后面课程学到高阶数据结构如红黑树等会用到三叉链。

3.4 二叉树的遍历

学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问节点所做的操作依赖于具体的应用问题。遍历时二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。

  • 前序遍历(Preorder Traversal)

亦称先序遍历,访问根结点的操作发生在遍历其左右子树之前。

  • 中序遍历(Inorder Traversal)

访问根节点的操作发生在遍历其左右子树之间

  • 后序遍历(Postorder Traversal)

访问根节点的操作在遍历其左右子树之后。

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

  • 层序遍历(LevelOrder)

设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

4.  二叉树功能的实现

  1. 二叉树结构定义(struct BinaryTreeNode)

代码实现:

typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;
  1. 二叉树节点的创建(CreatBinaryTree)
BTNode* BuyNode(BTDataType 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;
}
 
  1. 二叉树的前序遍历函数(PrevOrder)

递归不可能一直调用函数,因为这个过程一直在创建栈帧,即使栈再大,也会栈溢出。所以肯定会回归,回归的本质就是销毁栈帧。

递归是由两个部分构成:

1. 子问题

2. 返回条件

代码实现:

void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("N ");
		return;
	}
	printf("%d ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

相关文章:

  • Unity使用IL2CPP打包时,我们应该注意什么?如何避免(可以举例说明)
  • 创建虚拟环境以及配置对应的项目依赖
  • DeepSeek技术全景解析:架构创新与行业差异化竞争力
  • Spring Boot数据访问(JDBC)全解析:从基础配置到高级调优
  • 20-R 绘图 - 饼图
  • 游戏设计模式阅读 - 游戏循环
  • Spring Security+JWT (5)
  • 红队内网攻防渗透:内网渗透之内网对抗:实战项目VPC2打靶父子域三层路由某绒免杀下载突破约束委派域控提权
  • 深度解析:大模型在多显卡服务器下的通信机制与分布式训练——以DeepSeek、Ollama和vLLM为例
  • 安全面试4
  • 谷歌浏览器更新后导致的刷新数据无法显示
  • C++标准库提供了哪些智能指针类型以及它们的区别
  • 小红书运营教程(内容笔记01)
  • 网络安全 | 信息安全管理体系(ISMS)
  • Linux文件系统----磁盘级文件
  • 《GNU/Linux Shell命令全解析》
  • CSS背景属性
  • python——GUI图形用户界面编程
  • MySQL主从服务器配置教程
  • 【C++】模板初阶和STL简介
  • 青岛建设英文网站建设/seo什么意思
  • 怎么在360网站做词条/crm软件
  • 律师怎样做网站/游戏代理平台
  • 做网站平方根怎么表示/seo快速软件
  • 武汉建设委员会网站/电子商务
  • 做聊天网站的视频教程/推广营销是什么