二叉树的单旋分为: 左单旋 , 右单旋
判断对二叉树进行平衡操作要按照后序遍历的顺序
让不平航二叉树变为平衡二叉树
单旋的一些名词

以上图进行左单旋为例(可以参考下面左单旋)
旋转节点:不平衡节点为旋转节点(上图节点2)
新根:旋转之后称为根节点的节点(上图节点5)
变化分支:父级节点发生变化的那个分支(上图节点3)
不变分支:父级节点不变的那个分支(上图节点6)
左单旋
如图这是某一节点不平衡
如果左边浅,右边深,进行左单旋
左单旋就是绕着旋转节点逆时针旋转
左单旋时:
旋转节点:当前不平衡节点
新根:右子树的根节点
变化分支:右子树的左子树
不变化分支:右子树的右子树
进行左单旋后的示意图
重点
进行左单旋:
1:找到新根
2:找到变化分支
3:当前旋转节点的右孩子为变化分支
4:新根的左孩子为旋转节点
5:返回一个新的根节点
重点

左单旋动画示意图
两个结合这看 图二由于软件限制没办法将节点2作为旋转节点
图1 图2
右单旋
如图这是某一节点不平衡
如果左边深,右边浅,进行右单旋
右单旋是以旋转节点进行顺时针旋转
右单旋时:
旋转节点:当前不平衡节点
新根:左子树的根节点
变化分支:旋转节点的左子树的右子树
不变分时:旋转节点的左子树的左子树
右单旋后示意图
进行右单旋
1:找到新根
2:找到变化分支
3:当前旋转节点的左孩子为变化分支
4:新根的右孩子为旋转节点
5:返回一个新的根节点
动态示意图
代码实现左右单旋
class Node {constructor(value) {this.value = value;this.left = null;this.right = null;}}let node2 = new Node('2')let node5 = new Node('5')let node3 = new Node('3')let node6 = new Node('6')// 左单旋// node2.right = node5;// node5.right = node6;// node5.left = node3;// 右单旋node6.left = node3;node3.left = node2;node3.right = node5;/*** 判断是否为二叉平衡树* 平衡二叉的满足条件* 根节点的左子树与右子树的高度差不能超过1* 这棵二叉树的每个子树的符合第一条* @param {*} root 根节点* @returns Boolean*/function isBalanceTree(root) {if (!root) return true;// 获取左右子树的深度let left = getDeep(root.left);let right = getDeep(root.right);// 当左子树与右子树的深度差大于1说明不是二叉平衡树if (Math.abs(left - right) > 1) return false;// 遍历这个二叉树的每一个子树else return isBalanceTree(root.left) && isBalanceTree(root.right);}/*** 获取二叉树的深度* @param {*} root 节点* @returns Number 返回左右子树中最深的层数*/function getDeep(root) {if (!root) return 0;let left = getDeep(root.left);let right = getDeep(root.right);return Math.max(left, right) + 1;}/*** 利用单旋将二叉不平衡树变为二叉平衡树* @param {*} root 跟节点* @returns 返回平衡之后的根节点*/function change(root) {if (isBalanceTree(root)) return root; // 返回平衡之后的根节点// 走到这说明不是二叉平衡树// 判断平不平衡需要从下往上判断// 判断对二叉树进行平衡操作要按照后序遍历的顺序// 后序遍历 先左子树 后右子树 最后自己// 为何进行后序遍历,当根节点不是二叉平衡树,可能对子树进行单旋操作就成为二叉平衡树if (root.left != null) root.left = change(root.left); // change函数会返回平衡之后的跟节点,故需要接收返回的的根节点if (root.right != null) root.right = change(root.right);// change函数会返回平衡之后的跟节点,故需要接收返回的的根节点// 获取深度let leftTree = getDeep(root.left);let rightTree = getDeep(root.right);// 判断那里不符合二叉平衡树的要求if (Math.abs(leftTree - rightTree) < 2) return root;if (leftTree < rightTree) { //左浅 右深 左单旋return leftRotate(root)} else if (leftTree > rightTree) { //左深 右浅 右单旋return rightRotate(root)}}/*** 左单旋* 旋转节点:不平衡的节点为旋转节点* 新根:旋转节点的右子树的根节点* @param {*} root 旋转节点* @returns 新的根节点*/function leftRotate(root) {// 找到新根let newNode = root.right;// 找到变化分支let changeNode = newNode.left;// 当前旋转节点的右孩子为变化分支root.right = changeNode;// 新根的左孩子为旋转节点newNode.left = root;// 返回新的根节点return newNode;}/*** 右单旋* 旋转节点:不平衡的节点为旋转节点* 新根:旋转节点的左子树的根节点* @param {*} root 旋转节点* @returns 新的根节点*/function rightRotate(root) {// 找到新根let newNode = root.left;// 找到变化分支let changeNode = newNode.right;// 当前旋转节点的左孩子为变化分支root.left = changeNode// 新根的右孩子为旋转节点newNode.right = root;// 返回新的根节点return newNode;}// 测试左单旋// let root = change(node2);// 测试右单旋let root = change(node6);console.log(root)
为何判断对二叉树进行平衡操作要按照后序遍历的顺序
如图
节点5 不符合二叉平衡树的条件
节点6 不符合二叉平衡树的条件
当我们对节点6进行左单旋
你会发现现在它符合二叉平衡树啦
重点
判断平不平衡需要从下往上判断
判断对二叉树进行平衡操作要按照后序遍历的顺序
重点
