初识数据结构——二叉树从基础概念到实践应用

初识数据结构——二叉树从基础概念到实践应用


数据结构专栏 ⬅(click)

初识二叉树:从基础概念到实践应用🌳

一、树型结构基础

1.1 树的基本概念

在这里插入图片描述

树是一种非线性的数据结构,由n(n>0)个有限节点组成一个具有层次关系的集合。它看起来像一棵倒挂的树,根朝上而叶朝下。

关键特点:有且仅有一个根节点,没有前驱节点除根节点外,其余节点被分成M(M>0)个互不相交的子树树是递归定义的
重要术语结点的度:一个结点含有子树的个数树的度:树中所有结点度的最大值叶子结点:度为0的结点双亲结点/父结点:含有子结点的结点孩子结点/子结点:一个结点含有的子树的根结点根结点:没有双亲结点的结点结点的层次:从根开始定义,根为第1层树的高度/深度:树中结点的最大层次

1.2 树的表示方法

最常用的表示方法是孩子兄弟表示法

classNode{int value;// 树中存储的数据Node firstChild;// 第一个孩子引用Node nextBrother;// 下一个兄弟引用}
在这里插入图片描述

二、二叉树详解

2.1 二叉树概念

二叉树是结点的一个有限集合,该集合:

  1. 或者为空
  2. 或者由一个根节点加上两棵分别称为左子树和右子树的二叉树组成

特点

  • 二叉树不存在度大于2的结点

二叉树的子树有左右之分,次序不能颠倒,是有序树

在这里插入图片描述

2.2 特殊二叉树

  1. 满二叉树:每层的结点数都达到最大值。层数为K,结点总数是2^K-1

完全二叉树:深度为K,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从0至n-1的结点一一对应

在这里插入图片描述

2.3 二叉树的性质

  1. 非空二叉树的第i层最多有2^(i-1)个结点
  2. 深度为K的二叉树最大结点数是2^K-1
  3. 对于任何二叉树,n0(叶子结点) = n2(度为2的结点) + 1
  4. 具有n个结点的完全二叉树深度为⌈log₂(n+1)⌉
  5. 完全二叉树的父子结点关系:
    • 父结点序号:(i-1)/2
    • 左孩子序号:2i+1
    • 右孩子序号:2i+2

2.4 二叉树的存储

链式存储
// 孩子表示法classNode{int val;// 数据域Node left;// 左孩子引用,常常代表左孩⼦为根的整棵左⼦树 Node right;// 右孩子引用,常常代表右孩⼦为根的整棵右⼦树 }// 孩子双亲表示法classNode{int val;Node left;// 左孩子引用,常常代表左孩⼦为根的整棵左⼦树 Node right;// 右孩子引用,常常代表右孩⼦为根的整棵右⼦树 Node parent;// 当前节点的根节点}

三、二叉树遍历

遍历(Traversal)是指沿着某条搜索路线,依次对树中每个结点均做⼀次且仅做⼀次访问。访问结点所做的操作依赖于具体的应⽤问题(比如:打印节点内容、节点内容加1)。遍历是⼆叉树上最重要的操作之一,是二叉树上进行其它运算之基础。

在这里插入图片描述

3.1 递归遍历

  1. (NLR)前序遍历:根节点 -> 左子树 -> 右子树
  2. (LNR)中序遍历:左子树 -> 根节点 -> 右子树

(LRN)后序遍历:左子树 -> 右子树 -> 根节点

在这里插入图片描述
// 前序遍历voidpreOrder(Node root){if(root ==null)return;System.out.print(root.val +" ");preOrder(root.left);preOrder(root.right);}// 中序遍历voidinOrder(Node root){if(root ==null)return;inOrder(root.left);System.out.print(root.val +" ");inOrder(root.right);}// 后序遍历voidpostOrder(Node root){if(root ==null)return;postOrder(root.left);postOrder(root.right);System.out.print(root.val +" ");}

3.2 层序遍历

从根节点出发,按层次从上到下、从左到右访问结点。

voidlevelOrder(Node root){if(root ==null)return;Queue<Node> queue =newLinkedList<>(); queue.offer(root);while(!queue.isEmpty()){Node cur = queue.poll();System.out.print(cur.val +" ");if(cur.left !=null) queue.offer(cur.left);if(cur.right !=null) queue.offer(cur.right);}}

四、二叉树基本操作

代码示例:

// 获取节点个数intsize(Node root){if(root ==null)return0;return1+size(root.left)+size(root.right);}// 获取叶子节点个数intgetLeafNodeCount(Node root){if(root ==null)return0;if(root.left ==null&& root.right ==null)return1;returngetLeafNodeCount(root.left)+getLeafNodeCount(root.right);}// 获取第k层节点个数intgetKLevelNodeCount(Node root,int k){if(root ==null|| k <=0)return0;if(k ==1)return1;returngetKLevelNodeCount(root.left, k-1)+getKLevelNodeCount(root.right, k-1);}// 获取二叉树高度intgetHeight(Node root){if(root ==null)return0;return1+Math.max(getHeight(root.left),getHeight(root.right));}// 查找值为val的节点Nodefind(Node root,int val){if(root ==null)returnnull;if(root.val == val)return root;Node left =find(root.left, val);if(left !=null)return left;returnfind(root.right, val);}

结语

二叉树是数据结构中的核心内容,掌握好二叉树对于理解更复杂的数据结构和算法至关重要。建议读者在学习理论的同时,多动手实现代码,解决实际问题,才能真正掌握二叉树的精髓。


在这里插入图片描述

Read more

Flutter 组件 fluent_assertions 的适配 鸿蒙Harmony 实战 - 驾驭流式语义断言语法、实现鸿蒙端单元测试高可读性与复杂逻辑自证方案

Flutter 组件 fluent_assertions 的适配 鸿蒙Harmony 实战 - 驾驭流式语义断言语法、实现鸿蒙端单元测试高可读性与复杂逻辑自证方案

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 fluent_assertions 的适配 鸿蒙Harmony 实战 - 驾驭流式语义断言语法、实现鸿蒙端单元测试高可读性与复杂逻辑自证方案 前言 在鸿蒙(OpenHarmony)生态的大型分布式系统开发中,随着业务逻辑复杂度的指数级增长,原本简单的单元测试逐渐演变为由数百行冗长、枯燥且难以通过阅读理解其意图的 expect(result, isA<T>()) 堆砌而成的“代码仓库”。面对一个需要同时验证“返回值不为空 且 包含特定前缀 且 响应时间小于 50ms”的复合业务断言。如果仅仅依靠传统的 JUnit 风格写法。不仅会导致测试代码本身产生严重的维护债务,更会由于在测试失败时生成的机械化、无逻辑上下文的错误报文,引发开发者极其低效的排查过程。 我们需要一种“自然语言化、逻辑链式”的测试审计艺术。 fluent_

By Ne0inhk
【Linux】线程控制(二)

【Linux】线程控制(二)

文章目录 * 背景 * 🚩进程控制 * 线程计算1-100 * 🚩线程库 * c++11多线程 背景 Linux中没有真正的线程概念,而是复用进程数据结构和管理算法,用进程模拟线程 只有轻量级进程,不会提供线程的调用接口,而是提供轻量级进程的系统调用接口 但是我们用户需要线程调用,所以有pthread库帮我们封装了轻量级进程调用接口,我们可以直接使用线程接口 * 每个linux平台自带pthread库, * 编写多线程代码需要pthread库 线程接口 每个线程都有自己的ID, ⭐pthread_create不是系统调用,需链接 -pthread 🚩进程控制 快速使用一下 #include<iostream>#include<pthread.h>#include<unistd.h> using namespace std;void*threadRoutine(void*args){constchar* str=

By Ne0inhk
鸿蒙金融理财全栈项目——运维监控、性能优化、安全加固

鸿蒙金融理财全栈项目——运维监控、性能优化、安全加固

《鸿蒙APP开发从入门到精通》第20篇:鸿蒙金融理财全栈项目——运维监控、性能优化、安全加固 📊🔧🛡️ 内容承接与核心价值 这是《鸿蒙APP开发从入门到精通》的第20篇——运维监控、性能优化、安全加固篇,100%承接第19篇的生态合作、用户运营、数据变现架构,并基于金融场景的运维监控、性能优化、安全加固要求,设计并实现鸿蒙金融理财全栈项目的运维监控、性能优化、安全加固功能。 学习目标: * 掌握鸿蒙金融理财项目的运维监控设计与实现; * 实现应用监控、服务器监控、数据库监控; * 理解性能优化在金融场景的核心设计与实现; * 实现前端优化、后端优化、数据库优化; * 掌握安全加固在金融场景的设计与实现; * 实现代码加固、数据加密、安全审计; * 优化金融理财项目的用户体验(运维监控、性能优化、安全加固)。 学习重点: * 鸿蒙金融理财项目的运维监控设计原则; * 性能优化在金融场景的应用; * 安全加固在金融场景的设计要点。 一、 运维监控基础 🎯 1.1 运维监控定义 运维监控是指对金融理财项目的应用、

By Ne0inhk
Flutter 组件 jaspr_serverpod 适配鸿蒙 HarmonyOS 实战:前后端同构,构建全栈式组件渲染与高性能后端集成架构

Flutter 组件 jaspr_serverpod 适配鸿蒙 HarmonyOS 实战:前后端同构,构建全栈式组件渲染与高性能后端集成架构

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 组件 jaspr_serverpod 适配鸿蒙 HarmonyOS 实战:前后端同构,构建全栈式组件渲染与高性能后端集成架构 前言 在鸿蒙(OpenHarmony)生态迈向全栈式开发、涉及跨端组件复用及高性能服务端逻辑集成的背景下,如何实现前端 UI 组件与后端业务逻辑的“无缝类型对齐”,已成为提升全栈研发效率与系统稳定性的关键议题。在鸿蒙设备这类强调分布式架构与端云协同的环境下,如果前端应用(Jaspr)与后端引擎(Serverpod)依然依赖碎片的 REST 协议驱动,由于由于接口契约的离散性,极易由于由于“前后端模型失致”导致线上环境的数据解析崩溃或并发冲突。 我们需要一种能够支持全栈 Dart 编写、具备自动代码生成且支持服务器端渲染(SSR)的同构映射方案。 jaspr_serverpod 为 Flutter/Dart 开发者引入了“全栈闭环”开发模式。

By Ne0inhk