数据结构与算法-二叉树
树的定义
有很多数据的逻辑关系并不是线性关系,在实际场景中,常常存在着一对多,甚至是多对多的情况。
组织结构:
以上的数据结构,我们称为树
在数据结构中,树的定义如下:
树(tree)是n(n≥0)个节点的有限集。
当n=0时,称为空树。在任意一个非空树中,有如下特点。
- 有且仅有一个特定的称为根的节点。
- 当n>1时,其余节点可分为m(m>0)个互不相交的有限集
- 每一个集合本身又是一个树,并称为根的子树。
节点1是根节点(root)
,没有父节点
节点5、6、7、8是树的末端,没有“孩子”,被称为叶子节点(leaf)
节点2、3、4、是树的中端,有父节点,有孩子,被称为中间节点或枝节点
图中的虚线部分,是根节点1的其中一个子树
树的最大层级数,被称为树的高度或深度
,上图这个树的高度是4
树的分类
二叉树
二叉树(binary tree)
是树的一种特殊形式。二叉,顾名思义,这种树的每个节点最多有2个孩子节点。注意,这里是最多有2个,也可能只有1个,或者没有孩子节点。
二叉树节点的两个孩子节点,一个被称为左孩子(left child),一个被称为右孩子(right child)。这两个孩子节点的顺序是固定的,左孩子小于右孩子
。
满二叉树
一个二叉树的所有非叶子节点都存在左右孩子,并且所有叶子节点都在同一层级上,那么这个树就是满二叉树
完全二叉树
对一个有n个节点的二叉树,按层级顺序编号,则所有节点的编号为从1到n。如果这个树所有节点和同样深度的满二叉树的编号为从1到n的节点位置相同,则这个二叉树为完全二叉树
满二叉树要求所有分支都是满的;而完全二叉树只需保证最后一个节点之前的节点都齐全即可
二叉树的存储
二叉树属于逻辑结构,可以使用链表和数组进行存储。
链式存储
二叉树的每一个节点包含3部分
- 存储数据的data变量
- 指向左孩子的left指针
- 指向右孩子的right指针
数组存储
使用数组存储时,会按照层级顺序把二叉树的节点放到数组中对应的位置上。
如果某一个节点的左孩子或右孩子空缺,则数组的相应位置也空出来
寻址方式:
一个父节点的下标是n,那么它的左孩子节点下标就是2×n+1、右孩子节点下标就是2*(n+1)
对于一个稀疏的二叉树(孩子不满)来说,用数组表示法是非常浪费空间的,所以二叉树一般用链表存储实现。(二叉堆除外)
二叉树的遍历
二叉树,是典型的非线性数据结构,遍历时需要把非线性关联的节点转化成一个线性的序列,以不同的方式来遍历,遍历出的序列顺序也不同。
二叉树的遍历包括: 深度优先遍历
、广度优先遍历
。深度优先遍历又包含前序遍历
、中序遍历
、后序遍历
深度优先遍历
所谓深度优先,顾名思义,就是偏向于纵深,“一头扎到底”的访问方式
前序遍历
二叉树的前序遍历,输出顺序是根节点、左子树、右子树
中序遍历
二叉树的中序遍历,输出顺序是左子树、根节点、右子树
后序遍历
二叉树的后序遍历,输出顺序是左子树、右子树、根节点
广度优先遍历
也叫层序遍历,顾名思义,就是二叉树按照从根节点到叶子节点的层次关系,一层一层横向遍历各个节点。
时间复杂度
二叉查找树的插入和查找时间复杂度为:O(logn)
极端情况下二叉查找树退化成链表,时间复杂度为O(n),所以需要平衡二叉查找树
。