前言:
由于二叉查找树不是严格意义上的O(logN),为了查找时间复杂度能够严格意义上的O(logN),在二叉查找树的基础上进行改进,附加一个性质,即某棵树根节点的左右子树高度相差不能大于1。如果左右子树高度相差大于1,则需进行旋转调整。
定义:
平衡二叉树是一棵二叉查找树,且根节点的左右子树高度相差不能大于1。
其结构图如下:
当在AVL树中进行插入操作和删除操作时,有时候会失去平衡性,即父节点的左右子树高度相差大于1,此时就必须对该AVL树进行调整,使其满足AVL树的性质。这里采用旋转进行调整。
旋转:
平衡二叉树失去平衡性具有以下四种情况:
- 左子树的高度大于右子树高度,且相差大于1,同时左子树根节点的左孩子节点高度大于右孩子节点高度。此情况称为左左情况。
- 左子树的高度大于右子树高度,且相差大于1,同时左子树根节点的右孩子节点高度大于左孩子节点高度。此情况称为左右情况。
- 右子树的高度大于左子树高度,且相差大于1,同时右子树根节点的左孩子节点高度大于右孩子节点高度。此情况称为右左情况。
- 右子树的高度大于左子树高度,且相差大于1,同时右子树根节点的右孩子节点高度大于左孩子节点高度。此情况称为右右情况。
下图是对应上面四种不同情况的失衡结构图:
图2说明:
- 第一小图属于左左情况,根节点11的左子树(以节点6为根节点的树)高度大于右子树(以节点15为根节点的树)高度,且相差为2,同时左子树的根节点6的左孩子节点2的高度大于右孩子节点7的高度。
- 第二小图属于左右情况,根节点11的左子树(以节点6为根节点的树)高度大于右子树(以节点15为根节点的树)高度,且相差为2,同时左子树的根节点6的右孩子节点7的高度大于左孩子节点2的高度。
- 第三小图属于右左情况,根节点11的右子树(以节点15为根节点的树)高度大于左子树(以节点6为根节点的树)高度,且相差为2,同时右子树的根节点15的左孩子节点14的高度大于右孩子节点17的高度。
- 第四小图属于右右情况,根节点11的右子树(以节点15为根节点的树)高度大于左子树(以节点6为根节点的树)高度,且相差为2,同时右子树的根节点15的右孩子节点17的高度大于左孩子节点12的高度。
从图2分析可知,情况1(左左)和情况4(右右)是对称的,只需旋转一次即可,我们称为单旋转。情况2(左右)和情况3(右左)是对称的,需要旋转两次,我们称为双旋转。
单旋转:
单旋转是针对左左和右右情况的,只需旋转一次即可达到平衡。
情况1:左左
说明:此情况的二叉树是不平衡二叉树,旋转过程中,把左孩子节点6作为二叉树新的根节点,节点6的左子树不变,节点6的右子树作为二叉树原根节点11的的左子树,二叉树原根节点11作为新的二叉树的右子树。
情况4:右右
说明:此情况的二叉树是不平衡二叉树,旋转过程中,把右孩子节点15作为二叉树新的根节点,节点15的右子树不变,节点15的左子树作为二叉树原根节点11的的右子树,二叉树原根节点11作为新的二叉树的左子树。
双旋转:
双旋转是指不平衡二叉树必须经过两次旋转才能达到平衡。
情况2:左右
说明:首先对左子树节点6进行右右旋转的操作,在对二叉树根节点11进行左左旋转的操作。
情况3:右左
说明:首先对右子树节点15进行左左旋转的操作,在对二叉树根节点11进行右右旋转的操作。
相关操作:
平衡二叉树的插入、查找和删除操作跟二叉查找树的操作类似,只是在操作结束时,对二叉树进行调整,使其仍然是平衡二叉树。有关二叉查找树的操作在前面的博文《二叉查找树》已经记录过,在这里就不做记录。