在数据结构中树的用途其实并不大,用得更多的其实是二叉树。所以在本章我们将详细讲解二叉树。
一颗二叉树是结点的一个有限集合,该集合:
如图我们可知,二叉树的特点:
注意:对于任意的二叉树都是由以下几种情况复合而成的:
顾名思义,斜树就一定要是斜的,但是往哪边斜也是有区别的:
如图我们可知斜树的特点:
一个二叉树,如果每一个层的结点数都达到最大值(即结点的度为2),则这个二叉树就是满二叉树。
tip:
对于深度为K的,有n个结点的二叉树,按层序编号,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点——对应时称之为完全二叉树。
完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树引出来的。
注意:满二叉树 != 完全二叉树,但是满二叉树是一种特殊的完全二叉树。
tip:
二叉树一般可以使用两种结构存储,一种顺序存储,一种链式存储。
顺序结构存储就是使用数组存储, 一般使用数组 只适合表示完全二叉树, 因为不是完全二叉树会有空间的浪费。
在现实的使用中只有堆才会使用数组来存储二叉树,关于堆我们会在后续详细讲解。
二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。
tip:
数组下标体现了结点之间的逻辑关系
二叉树的链式存储结构是指,用链表来表示一颗二叉树,即用链来指示元素的逻辑关系。
通常的方法是链表中的每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址。
链表结构又分为二叉链和三叉链,现在我们学习中一般都是二叉链,后面学到高阶数据结构如红黑树等才会用到三叉链。
代码示例:
//重命名结点数据域类型
typedef int BTDataType;
//二叉链
struct BinaryTreeNode
{
struct BinaryTreeNode* _pLeft;//指向当前结点左孩子
struct BinaryTreeNode* _pRight;//指向当前结点右孩子
BTDataType _data;//当前结点值域
};
//三叉链
struct BinaryTreeNode
{
struct BinaryTreeNode* _pParent;//指向当前结点的双亲
struct BinaryTreeNode* _pLeft;//指向当前结点左孩子
struct BinaryTreeNode* _pRight;//指向当前结点右孩子
BTDataType _data;//当前结点值域
};