package com.dolay.twoForkedTree.threeForkChainListStorage; /** * created by Administrator on 2018/3/28/028 * projectName dataStructure 三叉链表存储结构实现平衡二叉树 * 平衡二叉树特点 * 平衡二叉树不仅需要满足二叉树的定义,还需要满足二叉排序树的定义,还需遵守任意结点 * 的左右子树高度差的绝对值不能超过1; * * * 平衡因子 * * 旋转 * */ public class BalancedBinaryTree<T extends Comparable<T>>{ private TreeNode rootTreeNode; public class TreeNode<T extends Comparable<T>> { T data; TreeNode left,right,parent; int balanceFactor; public TreeNode(T data, int balanceFactor) { this.data = data; this.left = null; this.right = null; this.parent = null; this.balanceFactor = balanceFactor; } public T getData() { return data; } public void setData(T data) { this.data = data; } public TreeNode getLeft() { return left; } public void setLeft(TreeNode left) { this.left = left; } public TreeNode getRight() { return right; } public void setRight(TreeNode right) { this.right = right; } public TreeNode getParent() { return parent; } public void setParent(TreeNode parent) { this.parent = parent; } public int getBalanceFactor() { return balanceFactor; } public void setBalanceFactor(int balanceFactor) { this.balanceFactor = balanceFactor; } } public BalancedBinaryTree() {} private boolean isEmpty() { return this.rootTreeNode == null; } /*获取根结点*/ private TreeNode root() { if(this.rootTreeNode == null) { throw new RuntimeException("no such the root node"); } return this.rootTreeNode; } /**************************************平衡二叉树算法核心开始*******************************************/ /*循环构建平衡二叉树*/ private TreeNode balancedBinaryTree(T[] dataArray) { try { if(dataArray != null && dataArray.length>0) { this.rootTreeNode = null; for(int i=0;i<dataArray.length;i++) { this.sortAlgorithm(dataArray[i]); } } }catch (Exception ex) { throw new RuntimeException(); } return this.rootTreeNode; } /*平衡二叉树添加结点算法*/ private void sortAlgorithm(T data) { TreeNode tempTreeNode = null, balancedNode = null; try{ tempTreeNode = this.rootTreeNode; while(tempTreeNode != null) { if(data.compareTo((T) tempTreeNode.data) < 0) { TreeNode nodeLeft = tempTreeNode.getLeft(); if(nodeLeft == null) { /*插入新增结点,并设置更新平衡因子*/ nodeLeft = new TreeNode(data, 0); nodeLeft.parent = tempTreeNode; tempTreeNode.left = nodeLeft; /*循环设置当前新增结点的父结点*/ balancedNode = nodeLeft; while(balancedNode.parent != null) { balancedNode.parent.balanceFactor = this.getTreeNodeBalanceFactor(balancedNode.parent); balancedNode = balancedNode.parent; } /*开始判断和选择是否设置平衡二叉树,由于当前新增结点的平衡因子为零,直接计算当前结点的父结点平衡因子*/ this.judgeDealBalancedBinaryTree(nodeLeft); break; }else { tempTreeNode = nodeLeft; } }else { TreeNode nodeRight = tempTreeNode.getRight(); if(nodeRight == null) { /*插入新增结点,并设置更新平衡因子*/ nodeRight = new TreeNode(data, 0); nodeRight.parent = tempTreeNode; tempTreeNode.right = nodeRight; /*循环设置当前新增结点的父结点*/ balancedNode = nodeRight; while(balancedNode.parent != null) { balancedNode.parent.balanceFactor = this.getTreeNodeBalanceFactor(balancedNode.parent); balancedNode = balancedNode.parent; } /*开始判断和选择是否设置平衡二叉树,由于当前新增结点的平衡因子为零,直接计算当前结点的父结点平衡因子*/ this.judgeDealBalancedBinaryTree(nodeRight); break; }else { tempTreeNode = nodeRight; } } } if(this.rootTreeNode == null) { this.rootTreeNode = new TreeNode(data, 0); } }catch (Exception ex){ ex.printStackTrace(); } } /*平衡二叉树新增结点成功后遍历并判断平衡二叉树是否还平衡*/ private void judgeDealBalancedBinaryTree(TreeNode treeNewNode) { try { /* * (1)、从新增结点开始逐个向父结点遍历,找到首个平衡因子的绝对值大于等于2的结点即可; * (2)、此结点即为离新增结点最近的最小不平衡结点,以此最近的最小不平衡结点为基准; * (3)、判断子最小不平衡结点和其子结点(具体是左子结点还是右子结点需要根据最小不平衡结点的值与新增结点值比较, * 新增结点值大于最小不平衡结点的值则找右子结点,否则为左)构成什么样的旋转类型LL,RR,LR,RL * */ TreeNode treeNode = treeNewNode; if(treeNode != null) { while(treeNode.parent != null) { if(Math.abs(treeNode.parent.balanceFactor)>=2) { /*此时已经找到离新增结点最近的最小不平衡子结点,完成第(1)、(2)步,开始进行第(3)步*/ String rotateType = this.judgeRotateType(treeNode.parent,treeNewNode); switch (rotateType) { case "LL" : //左左旋转 右旋转第一个L即可 this.leftToLeftRotate(treeNode.parent); break; case "RR" : //右右旋转 左旋转第一个R即可 this.rightToRightRotate(treeNode.parent); break; case "LR" : //左右旋转 先左旋转第二个R,使之变为LL,再右旋转第一个L即可 this.leftToRightRotate(treeNode.parent); break; case "RL" : //右左旋转 先右旋转第二个L,使之变为RR,再左旋转第一个R即可 this.RightToLeftRotate(treeNode.parent); break; default: break; } /*不论是否进行旋转,都需要重新定位总根结点,新增结点逐渐获取父结点,直到某个几点的父结点为null则此结点即为总根结点*/ while(treeNewNode.parent != null) { treeNewNode = treeNewNode.parent; } this.rootTreeNode = treeNewNode; //旋转完成,是否还需要进行当前while循环视情况而定 break; }else { treeNode = treeNode.parent; } } } }catch (Exception ex) { ex.printStackTrace(); } } /* * 根据最小不平衡子结点判断旋转类型 * @param TreeNode minNoBalancedNode 最小不平衡子结点 * @param TreeNode treeNewNode 当前新增的结点 * */ private String judgeRotateType(TreeNode minNoBalancedNode, TreeNode treeNewNode) { StringBuffer stringBuffer = new StringBuffer(""); try { TreeNode treeNode = minNoBalancedNode; while(treeNode != null) { if(treeNewNode.data.compareTo(treeNode.data) > 0) { //查找最小不平衡子结点的右子结点 /*此时得到第一个旋转类型R型*/ stringBuffer.append("R"); treeNode = treeNode.getRight(); }else { //查找最小不平衡子结点的左子结点 /*此时得到第一个旋转类型L型*/ stringBuffer.append("L"); treeNode = treeNode.getLeft(); } if(stringBuffer.toString().length() == 2) { //构成LL,RR,LR,RL即可,也即stringBuffer表示的旋转类型字母组合只能为两个,达到两个就跳出 break; } } }catch (Exception ex) { throw new RuntimeException(); } return stringBuffer.toString(); } /* * 左左旋转(LL) * @param TreeNode minNoBalancedNode //最小不平衡子结点 * */ private void leftToLeftRotate(TreeNode minNoBalancedNode) { try { if(minNoBalancedNode.parent != null) { minNoBalancedNode.parent.left = minNoBalancedNode.left; } minNoBalancedNode.left.parent = minNoBalancedNode.parent; if(minNoBalancedNode.left.right != null) { TreeNode tempTreeNode = minNoBalancedNode.left; minNoBalancedNode.left = tempTreeNode.right; tempTreeNode.right = minNoBalancedNode; minNoBalancedNode.left.parent = minNoBalancedNode; minNoBalancedNode.parent = tempTreeNode; }else { minNoBalancedNode.left.right = minNoBalancedNode; minNoBalancedNode.parent = minNoBalancedNode.left; minNoBalancedNode.left = null; } }catch (Exception ex) { throw new RuntimeException(); } } /* * 左右旋转(LR--->LL) 先左旋转第二个R,使之变为LL,再右旋转第一个L即可 * @param TreeNode minNoBalancedNode //最小不平衡子结点 * */ private void leftToRightRotate(TreeNode minNoBalancedNode) { try { /*先进行最小不平衡结点的下一个左结点的右旋转(即LR中R的左旋转)*/ TreeNode treeNodeL = minNoBalancedNode.getLeft(); treeNodeL.parent.left = treeNodeL.right; treeNodeL.right.parent = treeNodeL.parent; treeNodeL.parent = treeNodeL.right; if(treeNodeL.right.left != null) { TreeNode tempTreeNode = treeNodeL.right; treeNodeL.right.left.parent = treeNodeL; treeNodeL.right = treeNodeL.right.left; tempTreeNode.left = treeNodeL; }else { treeNodeL.right.left = treeNodeL; treeNodeL.right = null; } /*再进行最小不平衡结点的LL旋转*/ this.leftToLeftRotate(minNoBalancedNode); }catch (Exception ex) { throw new RuntimeException(); } } /* * 右右旋转(RR) 左旋转第一个R即可 * @param TreeNode minNoBalancedNode //最小不平衡子结点 * */ private void rightToRightRotate(TreeNode minNoBalancedNode) { try { if(minNoBalancedNode.parent != null) { minNoBalancedNode.parent.right = minNoBalancedNode.right; } minNoBalancedNode.right.parent = minNoBalancedNode.parent; if(minNoBalancedNode.right.left != null) { TreeNode tempTreeNode = minNoBalancedNode.right; minNoBalancedNode.right = tempTreeNode.left; tempTreeNode.left = minNoBalancedNode; minNoBalancedNode.right.parent = minNoBalancedNode; minNoBalancedNode.parent = tempTreeNode; }else { minNoBalancedNode.right.left = minNoBalancedNode; minNoBalancedNode.parent = minNoBalancedNode.right; minNoBalancedNode.right = null; } }catch (Exception ex) { throw new RuntimeException(); } } /* * 右左旋转(RL--->RR) 先右旋转第二个L,使之变为RR,再左旋转第一个R即可 * @param TreeNode minNoBalancedNode //最小不平衡子结点 * */ private void RightToLeftRotate(TreeNode minNoBalancedNode) { try { /*先进行最小不平衡结点的下一个右结点的右旋转(即RL中L的右旋转)*/ TreeNode treeNodeR = minNoBalancedNode.getRight(); treeNodeR.parent.right = treeNodeR.left; treeNodeR.left.parent = treeNodeR.parent; treeNodeR.parent = treeNodeR.left; if(treeNodeR.left.right != null) { TreeNode tempTreeNode = treeNodeR.left; treeNodeR.left.right.parent = treeNodeR; treeNodeR.left = treeNodeR.left.right; tempTreeNode.right = treeNodeR; }else { treeNodeR.left.right = treeNodeR; treeNodeR.left = null; } /*再进行最小不平衡结点的RR旋转*/ this.rightToRightRotate(minNoBalancedNode); }catch (Exception ex) { throw new RuntimeException(); } } /*返回当前结点平衡因子,将当前节点的左子树的第一个结点的深度减去右子树第一个结点的深度即为当前节点的平衡因子*/ private int getTreeNodeBalanceFactor(TreeNode treeNode) { if(treeNode == null) { throw new RuntimeException("no such the node"); } return this.getDeep(treeNode.getLeft())-this.getDeep(treeNode.getRight()); //取当前结点左子树高度减去右子树高度; } /*获取结点的高度*/ public int getDeep(TreeNode node) { if(node == null) { return 0; } if(node.left == null && node.right == null) { //只存在一个结点,此结点为根结点,并且此结点再无左右子结点 return 1; }else { int lDeep = this.getDeep(node.left); int rDeep = this.getDeep(node.right); //记录其所有左、右子树中较大的深度 int max = lDeep>rDeep?lDeep:rDeep; //返回其左右子树中较大的深度 + 1 return max+1; } } /**************************************平衡二叉树算法核心截止*******************************************/ public static void main(String[] args) { BalancedBinaryTree balancedBinaryTree = new BalancedBinaryTree(); Integer[] dataArray = new Integer[]{89,66,87,91,45,90,53,39,99,37}; balancedBinaryTree.balancedBinaryTree(dataArray); Integer[] dataArray1 = new Integer[]{3,2,1,4,5,6,7,10,9,8}; balancedBinaryTree.balancedBinaryTree(dataArray1); } }
java平衡二叉树的实现
最新推荐文章于 2024-05-20 09:00:00 发布