树的概念和结构
- 树是由n(n>=0)个有限节点组成的一个具有层次关系的集合。
- 由一个根节点生出若干子节点,然后从这些子节点继续生出下层子节点,不断重复这个过程直到没有数据可以被存储。
成树方式
顺序存储
- 使用数组存储,元素在内存内是连续分布的。
- 根节点的下标是0,接下来每一层的下标从左到右增加1。
- 访问节点:当前节点下标为
i
,访问其左子节点的下标为2i+1
,右子节点的下标为2i+2
。
链式存储
- 基本数据单元为节点:包含节点元素、左指针、右指针。
- 一个树由若干个这样的节点组成,节点之间由左右指针连接。
- 链式存储的二叉树节点定义方式:
struct TreeNode {
int val;//节点元素
TreeNode* left;//左指针
TreeNode* right;//右指针
TreeNode(int x) : val(x), left(Null), right(Null) {}
}
树的分类
满二叉树
- 除了叶子节点外,所有节点都有两个子节点的二叉树。
- 第一层节点数为20,第二层节点数为21,可以推导出第n层节点数为2n-1。
- 树的深度为k,则整个树的节点数为2k-1。
完全二叉树
- 除了最底层没有填满之外,其他层全部填满的二叉树,且最底层节点的填充顺序为从左到右填充。
- 若树的深度为k,最底层节点数为1~2k-1。
二叉搜索树
- 二叉搜索树是有序树。
- 性质:左子节点<根节点<右子节点
平衡二叉搜索树
- 平衡:左右两颗子树的高度差绝对值不超过1,并且左右两棵子树都满足平衡条件。
- 搜索:左子节点<根节点<右子节点
遍历方式
广度优先遍历(层序遍历)
- 一层一层遍历
- 一般用迭代法实现
宽度优先遍历
- 先顺着一个方向往深处走,遇到叶子节点再往回走。
- 前序遍历:根节点——>左子节点(子树)——>右子节点(子树)
- 中序遍历:左子节点(子树)——>根节点——>右子节点(子树)
- 后序遍历:左子节点(子树)——>右子节点(子树)——>根节点
数据结构总结
到现在已经了解了常见的数据结构:数组、链表、树、哈希表、字符串、栈与队列。
然而,在这些数据结构之间也有一些联系:一些数据结构可以由更基础的数据结构作为容器去实现。
现在把这些数据结构分为一级基础数据结构和二级基础数据结构来进行总结思考。(一般情况下)
一级基础数据结构可以用来实现二级基础数据结构。此外,会先分析一级基础数据结构的内在结构。
一级基础数据结构
- 数组
- 数据在内存中进行连续存储
- 逻辑结构上是线性结构,元素之间一对一
- 最经典的顺序存储结构
- 链表
- 由若干节点组成
- 节点包含:数据、指向下一个节点的指针
- 节点之间由指针相连
- 是最经典的链式存储结构
- 树(链式存储)
- 由若干节点组成
- 节点包含:数据、指向左右子节点的指针
- 节点之间由指针相连
二级基础数据结构
- 字符串
- 底层为字符数组,把字符一个个存储在一个数组中
- 可以使用数组的方法访问元素
- 哈希表
- 具有快速查找元素的功能
- 可以使用数组(使用索引访问元素)实现这样的功能
- 集合:可以使用红黑树实现
- 映射:可以使用红黑树实现
- 栈
- 先入后出的结构
- 在逻辑结构上是线性结构
- 主要使用数组和链表当作底层容器来实现
- SGI STL中栈是以deque为缺省情况下的底部结构
- 队列
- 先入先出的结构
- 在逻辑结构上是线性结构
- 主要使用数组和链表当作底层容器实现
- 优先级队列使用树(堆)当作底层容器来实现
- SGI STL中队列是以deque为缺省情况下的底部结构
- 新数据结构的定义就是在底层容器的基础上添加一些接口,定义一些行为。