1.树的概念
树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。如果将他的图画出来的话很像一棵树。
1.1名词概念
- 根结点:没有父结点(前驱节点)的结点;如上方A就是根结点
- 父结点或双亲结点:如果这个结点下方还有结点(孩子节点)那么称这个结点为下方结点的父结点;如上方A是B的父结点
- 孩子结点或子结点:一个结点含有的子树的根结点;如上方B是A的子结点
- 兄弟的结点:具有相同父结点的子结点互为兄弟结点;比如-D和E
- 堂兄弟结点:双亲在同一层的结点称为堂兄弟结点;比如-E和F
- 结点的度:一个结点含有的子树的个数(父亲拥有的孩子的个数);如A的结点的度是2
- 叶子结点:该结点的度为0(没有孩子)称该结点为叶子结点;比如-B,E,F,G结点
- 非终端结点或分支结点:度不为0的结点(有孩子);比如B,C
- 树的度:这棵树内各结点度的最大值:上方这棵树的度为2
- 结点的层次:定义为根结点为一层(也有些地方定义根结点为0层);
- 树的高度和深度:结点中的最大层次;比如上面这棵树的高度为3
- 结点的祖先:从根结点到该结点所经历的分支上的所有结点;上图A是所有结点的祖先
- 子孙:以某结点为根的子树中任意结点都称为该结点的子孙;上图所有节点都是A结点的祖先
- 森林:多颗互不相邻的数的集合;
1.2树的表示方法
树有很多种表示方法比如:直观表示法,双亲表示法,孩子表示法,孩子兄弟表示法,凹入表示法,广义表表示法,括号表示法。这里就不一一举例了,就了解一下其中最常见的孩子兄弟表示法。
一个指针域指向该结点的第一个孩子结点,另一个指针域指向该结点的下一个兄弟结点。
2.二叉树
2.1概念
二叉树是一个有限元素的集合,该集合或者为空、或者由一个称为根的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成。每个节点最多只能有两棵子树,且有左右之分。这意味着在二叉树中,任何一个结点的度都不大于2。如上第一个图就是一个二叉树
- 左斜树:只有左子树的二叉树
- 右斜树:只有右子树的二叉树
2.2特殊的二叉树
2.2.1满二叉树
- 深度为k且有2^k-1个结点
- 最下面一层只有叶子结点
- 所有结点的度都是2或0
- 深度相同满二叉树结点最多
2.2.2完全二叉树
高度为h的二叉树有n个结点,当且仅当其每个结点与高度为h的满二叉树中编号为1到n的结点一一对应
- 叶子结点只会出现在最后两层
- 最下面一层的叶子结点都集中在左边
- 如果有度为1的结点只能有一个并且是左孩子
- 其从第一层到n-1层一定是一颗满二叉树
- 在同样结点个数的二叉树中,完全二叉树深度最小
//完全二叉树不一定是满二叉树,但满二叉树一定是完全二叉树
2.3二叉树的性质
- 若规定根结点的层数为1,则一颗非空二叉树的第i层上最多有2^(i-1)个结点
- 若规定根结点的层数为1,则深度为h(第h层)的二叉树的最大结点数是2^h-1
- 对任何一棵二叉树,如果度为0的分支结点个数为n0,度为2的分结点点个数为n2则有n0=n2+1
- 若规定根结点的层数为1,具有n个结点的满二叉树的深度,h=log
3.二叉树的存储结构
3.1顺序储存
用一组连续的存储单元存放二又树中的结点元素,一般按照二叉树结点自上向下、自左向右的顺序存储。二叉树的顺序储存在物理上是一个数组,在逻辑是是一个二叉树如下图
顺序结构一般只适合用来存储完全二叉树,因为存储不完全二叉树会有空间浪费
3.1链式存储
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。
二叉链表构建
4.二叉树链式的构建和遍历
遍历是二叉树最重要的运算之一,二叉树的递归遍历可以分为,前序遍历,中序遍历,后序遍历
前序遍历:先访问根结点,再访问左子树,最后访问右子树(根->左子树->右子树)
中序遍历:先访问左子树,再访问根结点,最后访问右子树(左子树->根->右子树)
后序遍历:先访问左子树,再访问右子树,最后访问根结点(左子树->右子树->根)
还有一个层序遍历:按照从上到下、从左到右的顺序依次访问每个节点的数据。这种方法需要借助队列来实现,首先将根节点入队,然后开始执行循环操作——出队一个元素并访问它,然后将它的左儿子和右儿子依次入队,直到队列为空为止(我在里就不多做阐述)。
下面我用中序遍历来做一个例子
5.堆的概念和结构
5.1堆的概念
堆就是用数组实现的完全二叉树(不是平衡二叉树),所以他在物理上没有父节点或子节点。堆在物理结构上是一个数组,在逻辑结构上是一个数组(类似于二叉树的顺序存储)
在逻辑结构上每个父节点(parent)和子节点(child)的下标存在一定数量关系
leftchild=parent*2+1;
rightchild=parent*2+2;
parent=(leftchild-1)/2;
5.2堆的性质
堆可以分为大根堆(最大堆)和小根堆(最小堆)
- 小根堆:根结点的值最小,且父结点的值比每一个子节点的值都小
- 大根堆:根结点的值最大,且父结点的值比每一个子节点的值都大
5.3堆排序
以升序为例
升序要建大堆
5.3.1建堆
向下调整法
前提:根结点的左右子树必须是小堆
从根节点开始,将跟节点和其两个子节点中较小的那个进行比较,如果比这个字节点小,就交换父节点和子节点的值,依次向下递归调到叶子就中止,但是这种方法有一个致命的缺点,就是左右子树必须是小堆,在大部分情况下不会刚好左右子树都是小堆,那么就要自己创建。
以上图为例,我们可以发现dhi这棵树的左右子树都是小堆,可以利用向下调整法进行排序,之后,cdehI,这棵树的左右子树也变成了小堆,可以再次利用向下调整法进行排序,就这样一次向上调整,最后把整棵树的左右子树都变成了小堆,就可以利用向下调整法进行排序了。那么我们还有一个问题。就是怎么找到dhi这棵树,其实这棵树的根节点就是整棵树的最后一个非叶子节点