微信公众号:小超说这是查找算法系列文章的第一篇,助你快速入门二叉树算法
咱们首先来看一些图片:数组
其中,第1、2、四个都是树,第三个不是。树的特色很明显吧!微信
其中每一个元素叫作“节点”;用来链接相邻节点之间的关系,咱们称之为“父子关系”。例如在图一中,A节点是B节点的父节点,B节点是A节点的子结点,同时,B节点和Q节点是同一个父节点A的子节点,因此它们之间互相成为兄弟节点。咱们把没有父节点的节点称为根节点,也就是图一中的A节点。咱们把没有子节点的节点称为叶子节点,好比图一中的D、E、F、G节点。这些概念都是显而易见,但倒是最基本的东西。数据结构
二叉树,天然就是每一个节点最多有两个分支,即两个子节点的一种树,两个分支分别称为左子树和右子树。仍是那上面那张图举例,图1、图二和图四都是二叉树,由于它们每一个节点都最多含有两个子节点。其中,图一又称为满二叉树,图四又称为彻底二叉树。而之因此出现彻底二叉树的概念,实际上是基于二叉树的物理存储方式。函数
链式存储法:spa
咱们为每一个节点建立一个Node对象
:设计
class Node{ int data; Node left,right; }
每一个节点都是一个Node对象,它包含咱们所须要存储的数据,指向左子节点的引用,直向右子节点的引用,就像链表同样将整个树串起来。若是该节点没有左子节点,则Node.left==null
或者Node.right==null
.code
顺序存储法:对象
咱们把根节点储存在下标为i=1
的位置,那么左子节点储存在2*i=2
的位置,右子节点储存在下标为2*i+1=2
的位置。依此类推,完成树的存储。借助下标运算,咱们能够很轻松的从父节点跳转到左子节点和右子节点或者从任意一个子节点找到它的父节点。若是X的位置为i,则它的两个子节点的下标分别为2i
和2i+1
,它的父节点的位置为i/2
(这里结果向下取整)。递归
具体以下图所示:能够发现,只有彻底二叉树存储的效率才最高,最省内存
二叉树的遍历操做主要有三种
前序遍历是指,对于树中的任意节点来讲,先打印这个节点,而后再打印它的左子树,最后打印它的右子树。
中序遍历是指,对于树中的任意节点来讲,先打印它的左子树,而后再打印它自己,最后打印它的右子树。
后序遍历是指,对于树中的任意节点来讲,先打印它的左子树,而后再打印它的右子树,最后打印这个节点自己。
注意,这其中有点递归的味道
仍是以刚才的图为例:
具体的代码实现(写出递归便可):
public void preOrder(Node root){ if(root==null) return; System.out.println(root.data);//打印root节点的值 preOrder(root.left); preOrder(root.right); } public void inOrder(Node root){ if(root==null) return; inOrder(root.left); Systrm.out.println(root.data); inOrder(root.right); } public void inOrder(Node root){ if(root==null) return; inOrder(root.left) inOrder(root.right); Systrm.out.println(root.data); }
二叉树遍历的时间复杂度是O(n),这是由于每一个节点最多会被访问两次,(递归时函数进栈和出栈),因此遍历操做的访问次数跟节点的个数 n 成正比,也就是说二叉树遍历的时间复杂度是 O(n)。
通过上面的介绍,咱们已经大体对二叉树有了一个基本的认识,那么,二叉树存在的意义是什么呢?咱们能够基于这种数据结构设计出哪些高效的算法呢?下一次咱们将介绍二叉查找树(Binary Search Tree),咱们将定义一种数据结构并维护它的性质。
题外话:对于算法初学者,推荐一本十分 nice 的书籍 《算法第四版》,里面各类配图十分详细。若是你须要电子版文件,后台回复算法4便可得到下载连接。后台回复 算法01 送你一份 算法与数据结构思惟导图。最后,但愿咱们一块儿进步,一块儿成长!