思考题

二叉树有哪几种存储方式?什么样的二叉树适合用数组来存储?

树(Tree)

  • 根节点:没有父节点的节点
  • 叶子节点或者叶节点:没有子节点的节点叫做

树的高度、深度、层

举例说明:

  • 生活中,“高度”这个概念,其实就是从下往上度量,比如我们要度量第 10 层楼的高度、第 13 层楼的高度,起点都是地面。所以,树这种数据结构的高度也是一样,从最底层开始计数,并且计数的起点是 0。
  • “深度”这个概念在生活中是从上往下度量的,比如水中鱼的深度,是从水平面开始度量的。所以,树这种数据结构的深度也是类似的,从根结点开始度量,并且计数起点也是 0
  • “层数”跟深度的计算类似,不过,计数起点是 1,也就是说根节点位于第 1 层。

二叉树

定义:每个节点最多有两个“叉”,也就是两个子节点,分别是左子节点和右子节点。二叉树并不要求每个节点都有两个子节点,有的节点只有左子节点,有的节点只有右子节点。

满二叉树:叶子节点全都在最底层,除了叶子节点之外,每个节点都有左右两个子节点

完全二叉树:叶子节点都在最底下两层,最后一层的叶子节点都靠左排列,并且除了最后一层,其他层的节点个数都要达到最大

为什么要单独提出一种完全二叉树

首先了解如何表示一颗二叉树?存储一棵二叉树,我们有两种方法,一种是基于指针或者引用的二叉链式存储法,一种是基于数组的顺序存储法。

1、链式 存储:常用的存储方式。每个节点有三个字段,其中一个存储数据,另外两个是指向左右子节点的指针。我们只要拎住根节点,就可以通过左右子节点的指针,把整棵树都串起来

2、基于数组的顺序存储法。我们把根节点存储在下标 i = 1 的位置,那左子节点存储在下标 2 * i = 2 的位置,右子节点存储在 2 * i + 1 = 3 的位置。以此类推,B 节点的左子节点存储在 2 * i = 2 * 2 = 4 的位置,右子节点存储在 2 * i + 1 = 2 * 2 + 1 = 5 的位置。

总结:

  1. 如果节点 X 存储在数组中下标为 i 的位置,下标为 2 * i 的位置存储的就是左子节点,下标为 2 * i + 1 的位置存储的就是右子节点。一般情况下,为了方便计算子节点,根节点会存储在下标为 1 的位置),这样就可以通过下标计算,把整棵树都串起来。
  2. 一棵完全二叉树,所以仅仅“浪费”了一个下标为 0 的存储位置。如果是非完全二叉树,会浪费比较多的存储空间
  3. 如果某棵二叉树是一棵完全二叉树,那用数组存储最节省内存。数组的存储方式并不需要像链式存储法存储额外的左右子节点的指针。这也是为什么完全二叉树会单独拎出来的原因,也是为什么完全二叉树要求最后一层的子节点都靠左的原因。
  4. 堆和堆排序的时候,你会发现,堆其实就是一种完全二叉树,最常用的存储方式就是数组。

二叉树的遍历

如何打印遍历树的所有节点呢?经典的方法有三种,前序遍历、中序遍历和后序遍历。其中,前、中、后序,表示的是节点与它的左右子树节点遍历打印的先后顺序。

  • 前序遍历是指,对于树中的任意节点来说,先打印这个节点,然后再打印它的左子树,最后打印它的右子树。
  • 中序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它本身,最后打印它的右子树。
  • 后序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身。

二叉树的前、中、后序遍历就是一个递归的过程。比如,前序遍历,其实就是先打印根节点,然后再递归地打印左子树,最后递归地打印右子树。写递归的关键是写出递推公式,而写出递推公式的关键是如果要解决问题A,假设子问题B\C都已经解决,再来看如何利用B\C来解决A。


前序遍历的递推公式:
preOrder(r) = print r->preOrder(r->left)->preOrder(r->right)中序遍历的递推公式:
inOrder(r) = inOrder(r->left)->print r->inOrder(r->right)后序遍历的递推公式:
postOrder(r) = postOrder(r->left)->postOrder(r->right)->print r

void preOrder(Node* root) {if (root == null) return;print root // 此处为伪代码,表示打印root节点preOrder(root->left);preOrder(root->right);
}void inOrder(Node* root) {if (root == null) return;inOrder(root->left);print root // 此处为伪代码,表示打印root节点inOrder(root->right);
}void postOrder(Node* root) {if (root == null) return;postOrder(root->left);postOrder(root->right);print root // 此处为伪代码,表示打印root节点
}

二叉树遍历的时间复杂度是多少吗?前面画的前、中、后序遍历的顺序图,可以看出每个节点最多会被访问两次,遍历操作的时间复杂度跟节点的个数 n 成正比,也就是说二叉树遍历的时间复杂度是 O(n)。

23 | 二叉树基础(上):什么样的二叉树适合用数组来存储?相关推荐

  1. 二叉树基础(上):什么样的二叉树适合用数组来存储?

    其实这段时间一直在刷lc,但是还是感觉树图写的不太行,就重新来学习总结了. 首先提出疑问:二叉树有哪几种存储方式?什么样的二叉树适合用数组来存储? 待着问题,然后来学习今天的内容 树 我们首先来看,什 ...

  2. [剑指offer]面试题23:从上往下打印二叉树

    面试题23:从上往下打印二叉树 题目:从上往下打印出二叉树的每个结点,同一层的结点按照从左到右的顺序打印.例如输入图4.5中的二叉树,则依次打印出8.6.10.5.7.9.11. 二叉树结点的定义如下 ...

  3. 《恋上数据结构第1季》二叉树基础、真二叉树、满二叉树、完全二叉树、二叉树的遍历(重点)

    二叉树(Binary Tree) 树(Tree)的基本概念 有序树.无序树.森林 二叉树(Binary Tree) 二叉树的性质 真二叉树(Proper Binary Tree) 满二叉树(Full ...

  4. 剑指offer——面试题23:从上往下打印二叉树

    剑指offer--面试题23:从上往下打印二叉树 Solution1: 典型的BFS算法! 思路一开始没想到,按照书上的思路写的答案... 注意:deque是双向队列,在头尾插入都很快! /* str ...

  5. 计算机二级二叉树基础知识,2017年计算机二级公共基础知识学习教程:树与二叉树...

    (六)树与二叉树 1.树的基本概念 树是一种简单的非线性结构.在树结构中,数据元素之间有着明显的层次结构.在树的图形表示中,用直线连接两端的结点,上端点为前件,下端点为后件. 在树结构中,每一个结点只 ...

  6. 【数据结构与算法基础】树与二叉树的互化

    前言 数据结构,一门数据处理的艺术,精巧的结构在一个又一个算法下发挥着他们无与伦比的高效和精密之美,在为信息技术打下坚实地基的同时,也令无数开发者和探索者为之着迷. 也因如此,它作为博主大二上学期最重 ...

  7. c++编写算法判断二叉树是否为完全二叉树_[校招-算法题] 二叉树基础算法1

    二叉树是面试中常考的数据结构,因为涉及大量指针操作,因此可以考察思维的严谨性和灵活性.但是校招中的二叉树题规律性很强,因此需要总结一下. 各种常见的二叉树概念 二叉树:每个结点最多有两个子树(左子树和 ...

  8. 数据结构与算法一 - 二叉树基础

    前言 树是数据结构中的重中之重,尤其以各类二叉树为学习的难点.一直以来,对于树的掌握都是模棱两可的状态,现在希望通过写一个关于二叉树的专题系列.在学习与总结的同时更加深入的了解掌握二叉树.本系列文章将 ...

  9. 二叉树的基本特性和二叉树的几种基本操作的机制_深入理解二叉树01 二叉树基础

    数据结构是所有的程序员就业过程中无法回避的知识,最近在回顾数据结构的内容,因此会不定期的推出一些数据结构的文章,分享自己的笔记. 树是数据结构中的重点,由于二叉树又是树中的重中之重.二叉树的应用也非常 ...

最新文章

  1. 如何实现手机自动适应网页
  2. System.LazyT 延迟加载
  3. day1 of python
  4. IP、TCP、UDP数据包长度问题
  5. 01_反射_02_反射类的构造方法
  6. Snowflake核心技术解读系列——架构设计
  7. Oracle闪回报错,oracle 闪回区满了,ORA-19815
  8. 第三方插件渗透攻击之KingView
  9. 机器学习算法数学基础之——微积分篇(1)
  10. java文件上传,返回访问url
  11. 京东618大促,全店商品如何导出?
  12. python用scrapy爬取58同城的租房信息
  13. 非视距微波传输抗干扰特性
  14. 2021年“羊城杯”网络安全大赛部分Writeup
  15. python函数库分类及实例_Python中Scikit-Learn库的分类方法总览
  16. vmware虚拟机安装maca苹果系统,滚动条无限重启
  17. 白鹭引擎正式支持微信小游戏开发
  18. Unity Steam_VR 开发工具插件 VRTK自带案例分析(第一部分)
  19. 99、插值法,函数逼近,曲线拟和,数值积分,数值微分,解线性方程组的直接方法,解线性方程组的迭代法,非线性方程求根,常微分方程的数值解法...
  20. 低成本2.4G SOC(NYA054E)灯控遥控芯片方案-CI2454/CI2451

热门文章

  1. 前端学习(1672):前端系列实战课程之加速减速运动
  2. 前端学习(1299):gulp插件
  3. 前端学习(693):for循环案例之求出偶数奇数之和
  4. 前端学习(478):前端简介2
  5. spring学习(8):log4j.properties 详解与配置步骤
  6. 50session的销毁会话和超时管理
  7. java学习(1):学生管理系统1
  8. Qt 调用VISA库通过SCPI程控仪器-以IT8906A电子负载为例
  9. 哈夫曼字符串编码c语言实现,基于哈夫曼(haffuman)算法的文件压缩的实现(C语言)(原创)...
  10. 你所忽略的,覆盖equals时需要注意的事项《effective java》