《STL源码剖析》笔记-树的介绍

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/WizardtoH/article/details/82811972

上一篇:《STL源码剖析》笔记-priority_queue、heap算法

序列式容器介绍完后就是关联式容器,关联式容器内部数据结构大多是平衡二叉树以获得较好的搜寻效率,因此先对树进行大概的了解。

树由节点(nodes)和边(edges)构成。整棵树有一个最上端节点,称为根节点(root)。每个节点可以拥有具有方向性的边(directed edges),用来和其他节点相连。相连节点之中,在上者称为父节点(parent),在下者称为子节点(child)。无子节点者称为叶节点(leaf)。子节点可以存在多个,如果最多只允许两个子节点,即所谓二叉树(binary tree)。不同的节点如果拥有相同的父节点,则彼此互为兄弟节点(siblings)。根节点至任何节点直接有唯一路径(path),路径所经过的边数,称为路径长度(length)。根节点至任一节点的路径长度,即所谓该节点的深度(depth)。根节点的深度永远是0。某节点至其最深子节点(叶节点)的路径长度,称为该节点的高度(height)。整棵树的高度,便以根节点的高度来代表。任何节点的大小(size)是指其所有子代(包括自己)的节点总数。
在这里插入图片描述

二叉搜索树(binary search tree)

二叉树的子节点最多只能有两个,二叉搜索树,可提供对数时间的元素插入和访问 。二叉搜索树的节点放置规则是:任何节点的键值一定大于其左子树中的每一个节点的键值,并小于其右子树中的每一个节点的键值。因此,从根节点一直往左走,直至无路可走,即得最小元素;从根节点一直往右走,直至无右路可走,即得最大元素。
在这里插入图片描述

二叉搜索树的查找比较简单,一直向左或向右即可。二叉搜索树插入新元素时,可以从根节点开始,遇键值较大者就向左,遇键值较小者就向右,一直到尾端,即为插入点。二叉搜索树移除操作可分两种,如果A只有一个子节点,我们就直接将A的子节点连至A的父节点,并将A删除;如果A有两个子节点,我们就以右子树内的最小节点取代A,右子书的最小节点很容易获得并且满足二叉搜索树的条件。

平衡二叉搜索树

二叉搜索树可能会因为输入数值不够随机或者一些插入删除操作导致失去平衡。
在这里插入图片描述

所谓树形平衡与否,并没有一个绝对的测量标准。“平衡”的大致意义是:没有任何一个节点过深(深度过大)。不同的平衡条件,造就不同的效率表现,以及不同的实现复杂度。有数种特殊结构如AVL-tree、RB-tree、AA-tree,均可实现平衡二叉搜索树,它们比一般二叉搜索树复杂。因此,插入节点和删除节点的平均时间也比较长,但是它们可以避免极难应付的最坏情况,况且由于它们总是保持某种程度的平衡,所以元素的访问时间平均而言也就比较少,一般而言其搜素时间可节省25%左右。

AVL tree(Adelson-Velskii-Landis Tree)

AVL tree是一个“加上了额外平衡条件”的二叉搜索树。其平衡条件的建立是为了确保整棵树的深度为O(logN)。AVL tree要求任何节点的左右子树高度相差最多为1。这是一个较弱的条件,但是仍然能够保证对数深度的平衡状态。
在这里插入图片描述

调整“插入节点至根节点”路径上,平衡状态被破坏之各节点种最深的那一个,便可使得整棵树重新获得平衡。假设该最深节点X,由于节点最多拥有两个子节点,二所谓“平衡被破坏”意味着X的左右两棵子树的高度相差2,因此可以分为一些四种情况:

  • 插入点位于X的左子节点的左子树——左左。
  • 插入点位于X的左子节点的右子树——左右。
  • 插入点位于X的右子节点的左子树——右左。
  • 插入点位于X的右子节点的右子树——右右。
    在这里插入图片描述

情况1/4彼此对称,称为外侧插入,可采用单选转操作调整解决;情况2/3彼此对此对此,称为内侧插入,可采用双旋转调整解决。

单旋转(Single Rotation)、双旋转(Double Rotation)

不平衡外侧插入的解决使用单旋转:
在这里插入图片描述

不平衡内侧插入的解决使用双旋转:
在这里插入图片描述

下一篇:《STL源码剖析》笔记-RB-tree

猜你喜欢

转载自blog.csdn.net/WizardtoH/article/details/82811972