树与二叉树
树是一种数据结构
树是一种可以递归定义的数据机构
树由n个节点组成。如果n=0,则是一棵空树
如果n>0,则存在一个节点是树的根节点,其他节点可以分为m个集合,每个集合本身又是一棵树。
基本概念
根节点:最上层的一个节点,没有父节点,只有子节点。
叶子结点:最下层的节点,没有子节点
树的深度:输的层数,上图有4层
树的度:输的节点分叉最多的一个节点的分叉数量。上图可以看出来根节点分叉最多,有5个,因此这个树的度为5
二叉树
度数不超过2的树叫做二叉树
满二叉树
二叉树的每层阶段属都达到最大值的二叉树叫做满二叉树。
完全二叉树
叶子节点只能出现在最下层和次下层,并且最下面一层的节点都集中在该层最左边的若干位置的二叉树。
二叉树的存储方式
链式存储方式
顺序存储方式
堆
堆:一种特殊的完全二叉树结构
大根堆:一棵完全二叉树,满足任一节点都比其子节点大。
小根堆:一棵完全二叉树,满足任一节点都比其子节点小。
堆的向下调整
假设节点的左右子树都是堆,但自身不是堆,可以通过一次向下调整将其变换成一个堆。
一个列表可以构成一个二叉树。如[3, 9, 8, 6, 7, 4, 1, 2, 3, 1, 0]可以构成如下完全二叉树,每个节点代表一个数,节点旁边的数字是其对应的索引值。
父节点和子节点的索引关系表示如下:
假设父节点索引值为n,则左子节点的索引值为为2n+1,右子节点的索引值为2n+2.
反之,如果已知子节点的索引值为k,则其对应父节点的索引值为(k-1)//2 (//: 整除符号)
如图所示,这里以大根堆的标准为例,根节点数字为3,要小于他的两个子节点,两个子节点均可以构成堆。这时使用一次向下调整即可将整个完全二叉树变为堆。所谓向下调整,就是将不满足条件的这个父节点和它的子节点中较大的一个互换位置。
再进行一次向下调整,即可成为大根堆。
堆排序
一般步骤为:
- 建立堆。
- 得到堆顶元素,为最大元素。
- 去掉对顶,将堆最后一个元素放到堆顶,此时可通过一次调整重新使堆有序。
- 堆顶元素为第二大元素。
- 重复步骤三,直到堆变空。
构造堆
从最底层的最左边一个子树开始,做向下调整,从左往右从下往上依次对所有子树进行调整,最后即可形成一个大根堆。
假设,原完全二叉树如下:
先从最底层最左边一个子树进行向下调整:
调整之后得到:
再向右查看下一个子树:
符合大根堆结构,不需要调整。接续看上一层最右边的树:
仍然不需要调整,继续向左查看。因为最底层的已经成为堆了,所以向左查看时就不需要再包含最底层的节点了。
需要向下调整:
再向上一层:
需要向下调整:
发现还不符合堆结构,需要继续向下调整。
以上便实现了一个堆的构造。
堆排序
以上边构造出来的堆为例,进行堆排序。
首先,将根节点上的数与最底层最右边的元素互换位置,再经过向下调整形成堆结构,此时第二大的元素就在根节点处。
然后,出去刚刚落下来的元素外(上图中的9),剩下的元素继续寻找最底层最右边的元素和根节点上的数字进行交换,再做向下调整,即可实现第二个元素的归位。
依次类推,最终可以实现所有元素的归位。