树(Tree)
本文作为树数据结构的第一篇,主要介绍树和二叉树的一些基本概念和术语;然后介绍了树结构的优缺点。树结构中的概念较多,所以需要在一开始就打好基础。
1. 定义
n个节点构成的有限集合。
2. 特点和对比
下面是对树、链表和数组的优缺点进行比较的简单表格:
| 结构 | 优点 | 缺点 |
|---|---|---|
| 树 | - 支持高效的数据搜索和插入操作 - 自然地组织数据,适用于层次结构的问题 - 具有平衡树性质时,保持良好的性能 | - 实现复杂度较高 - 操作较为复杂,需要维护树的结构 - 需要额外空间存储节点关系 |
| 链表 | - 动态大小,便于插入和删除元素 - 内存管理灵活,无需连续的内存块 - 可以高效地在任意位置添加或删除元素 | - 访问元素的时间复杂度为 O(n),需要遍历链表 - 不支持随机访问,需要从头开始顺序查找元素 - 需要额外的指针存储节点间的链接关系等导致占用更多内存 |
| 数组 | - 随机访问元素的时间复杂度为 O(1) - 紧凑的内存布局,利于缓存命中率 - 直接存储数据本身,无需额外空间存储节点关系 | - 大小固定,需要提前分配足够的空间 - 插入和删除元素涉及数据的移动,效率较低 - 内存管理困难,无法快速调整大小 |
3. 使用时机
树数据结构在以下情况下特别适用:
- 层次性数据:当需要组织和表示具有层级关系的数据时,树结构是一种自然的选择。例如,文件系统中的目录结构、组织机构图等。
- 快速搜索和插入:树的搜索和插入操作在平衡树(如二叉搜索树、B树)的情况下具有快速的时间复杂度,通常为对数时间复杂度。如果需要高效地进行这些操作,树是一个优秀的选择。
- 排序和范围查询:某些树结构(如平衡二叉搜索树)可以保持元素有序,使得范围查询和排序操作更加高效。如果需要经常执行这些操作,树结构往往比较合适。
- 树形算法:许多算法和问题的解决方案都基于树的结构。例如,深度优先搜索(DFS)、广度优先搜索(BFS)、最小生成树(MST)、哈夫曼编码等都使用树结构来实现。
需要注意的是,树结构的实现相对复杂一些,涉及到节点关系的维护和平衡等问题。因此,在不满足上述条件或者需求较简单时,可能会选择其他更简单的数据结构,如数组或链表。
总结:复杂的数据结构解决复杂的问题,当链表和数组搞不定的时候就应该用树了。
4. 术语
- 空树:树中的节点数目为0的时候,为空树;
- 子树(SubTree):除了根节点之外的其它节点都可以看成是互不相交的子树;
- 根(Root):树中的第一个节点,经常使用字母r表示;
- 层:树可以看成是由一层叠一层的节点组成的数据结构,层中容纳了属于此层的节点;
- 深度:树的层数;
- 叶子节点:没有子节点的节点;
- 父节点:节点的上层节点;
- 左子节点:二叉树中父节点的左边孩子;
- 右子节点:二叉树中父节点的右边孩子;
- 兄弟节点:同一个父节点的各个节点之间互为兄弟节点,在二叉树中左子节点和右子节点互为兄弟节点;
- 深度:从根结点到某个节点的最长路径的长度。
5. 二叉树
- 如果树种的每一个父节点都只有两个子节点,这两个子节点分别称为:
左子节点和右子节点。
5.1 二叉树的重要性
- 足够简单,因此处理方式和途径是有限的;
- 无论哪种树都可以根据一定的规则快速转化成二叉树;
5.2 转成二叉树
树这种数据结构有一个特点,那就是节点不论是什么组成方式,都可以根据一种规则转化成二叉树,这种转化方法叫做:儿子-兄弟表示法旋转45度 ,其原理也很简单,使用一句话就可以概括:节点的左边第一个子节点作为转变之后二叉树的左子节点,而节点右边最近的兄弟节点作为其右子节点 。
5.3 二叉树特点
- 可以为空;
- 第i层最大节点数目:2**(i-1), i>0;
- n层满二叉树的节点数目为:2**n-1, n>0
- 满足关系:n0 = n2 + 1, 其中n0指的是叶子节点,n2指的是度为2的非叶子节点,即有两个子节点的节点
5.4 完美二叉树
除了最后一层节点之外,其他层节点都有两个子节点的二叉树称为满二叉树,也就是完美二叉树。
5.5 完全二叉树
除了最后一层,其余各层节点都达到最大值;并且最后一层缺失的节点的右侧不能再有节点。满二叉树可以看成是特殊的完全二叉树
6. 二叉树的实现
6.1 存储结构
二叉树实现一般是使用链表作为其基础结构的!
6.2 节点
二叉树中的节点node一般由三部分组成:left,data,right,其中left保持对其左子节点的引用,data保存数据,right保持对其右子节点的引用。