D13-平衡二叉树[Java数据结构和算法]
Posted erfishing
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了D13-平衡二叉树[Java数据结构和算法]相关的知识,希望对你有一定的参考价值。
1.平衡二叉树基本介绍
1.1平衡二叉树又叫平衡二叉搜索树(Selg-balancing binary search tree),又叫AVL树,可以保证查询效率较高;
1.2 平衡二叉树是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是平衡二叉树。
1.3 平衡二叉树的常用实现方法有红黑树,AVL,替罪羊树,Treap,伸展树等;
2. AVL左旋转
2.1 左旋转流程(右子树的高度高)
2.2 右旋转流程(左子树的高度高)
2.3 双旋转,存在以下的情况不能单单进行一方旋转
2.4 代码实现
1 package cn.atguigu.AVL; 2 3 4 public class AVLTreeDemo 5 6 public static void main(String[] args) 7 // int[] arr= 4,3,6,5,7,8; 8 // int[] arr= 10,12,8,9,7,6; 9 int[] arr= 10,11,7,6,8,9; 10 //创建AVLTree对象 11 AVLTree avlTree=new AVLTree(); 12 //添加节点 13 for (int i = 0; i < arr.length; i++) 14 avlTree.add(new Node(arr[i])); 15 16 17 //遍历 18 System.out.println("中序遍历"); 19 avlTree.infixOrder(); 20 21 System.out.println("做平衡处理"); 22 System.out.println("left树的高度="+avlTree.getRoot().leftHeight()); 23 System.out.println("right树的高度="+avlTree.getRoot().rightHeight()); 24 25 26 27 28 //创建AVL树 29 class AVLTree 30 private Node root; 31 32 public Node getRoot() 33 return root; 34 35 36 // 查找要删除的节点 37 public Node search(int value) 38 if (root == null) 39 return null; 40 else 41 return root.search(value); 42 43 44 45 // 查找要删除节点的父节点 46 public Node searchParent(int value) 47 if (root == null) 48 return root; 49 else 50 return root.searchParent(value); 51 52 53 54 /** 55 * 1.返回以node为根节点的二叉排序树的最小节点的值 2.删除以node为根节点的二叉排序树的最小节点的值 56 * 57 * @param node 传入的节点,当作二叉排序树的根节点 58 * @return 返回以node为根节点的二叉排序树的最小节点的值 59 */ 60 public int delRightTreeMin(Node node) 61 Node target = node; 62 // 循环查找的左节点,会找到最小值 63 while (target.left != null) 64 target = target.left; 65 66 // 这是target指向了最小节点 67 // 删除最小节点 68 delNode(target.value); 69 return target.value; 70 71 72 // 删除节点 73 public void delNode(int value) 74 75 if (root == null) 76 return; 77 else 78 // 找到要删除的节点targetNode; 79 Node targetNode = root.search(value); 80 if (targetNode == null) 81 return;// 如果没有找到该接待你 82 // 如果当前这颗二叉排序树只有一个节点 83 if (root.left == null && root.right == null) 84 root = null; 85 return; 86 87 // 找到targetNode的父节点 88 Node parent = root.searchParent(value); 89 // 如果删除的节点是叶子节点 90 if (targetNode.left == null && targetNode.right == null) 91 if (parent.left != null && parent.left.value == value) // 判断targetNode是父节点的左子节点还是右子节点 92 parent.left = null; 93 else if (parent.right != null && parent.right.value == value) // 是右子节点 94 parent.right = null; 95 96 else if (targetNode.left != null && targetNode.right != null) // targetNode有左子树和右子树 97 int minVal = delRightTreeMin(targetNode.right); 98 targetNode.value = minVal; 99 else // 删除只有一颗子树的节点 100 // 如果要删除的节点有左子节点 101 if (targetNode.left != null) 102 if (parent != null) 103 if (parent.left.value == value) // targetNode是parent的左子节点 104 parent.left = targetNode.left; 105 else // targetNode是parent的右子节点 106 parent.right = targetNode.left; 107 108 else 109 root = targetNode.left; 110 111 else 112 if (parent != null) 113 // 如果要删除的节点有右子节点 114 if (parent.left.value == value) // targetNode是parent的左子节点 115 parent.left = targetNode.right; 116 else // targetNode是parent的右子节点 117 parent.right = targetNode.right; 118 119 else 120 root = targetNode.right; 121 122 123 124 125 126 127 128 // 添加节点的方法 129 public void add(Node node) 130 if (root == null) 131 root = node;// 如果root为空,直接让root指向node 132 else 133 root.add(node); 134 135 136 137 // 重载 138 public void infixOrder() 139 this.infixOrder(root); 140 141 142 // 中序遍历方法 143 public void infixOrder(Node root) 144 if (root == null) 145 System.out.println("树为空,无法遍历"); 146 else 147 root.infixOrder(); 148 149 150 151 //创建NOde节点 152 class Node 153 int value; 154 Node left; 155 Node right; 156 public Node(int value) 157 this.value = value; 158 159 //返回左子树的高度 160 public int leftHeight() 161 if(left==null) 162 return 0; 163 164 return left.height(); 165 166 //返回右子树的高度 167 public int rightHeight() 168 if(right==null) 169 return 0; 170 171 return right.height(); 172 173 //返回当前节点的高度,以该节点为树的高度 174 public int height() 175 return Math.max(left==null? 0:left.height(), right==null? 0:right.height())+1; 176 177 178 @Override 179 public String toString() 180 return "Node [value=" + value + "]"; 181 182 183 //右旋转 184 private void rightRotate() 185 Node newNode=new Node(value); 186 newNode.right=right; 187 newNode.left=left.right; 188 value=left.value; 189 left=left.left; 190 right=newNode; 191 192 193 //左旋转方法 194 private void leftRotate() 195 //创建新的节点,以当前根节点的值 196 Node newNode=new Node(value); 197 //把新的节点的左子树设置成当前节点的左子树 198 newNode.left=left; 199 //把新的节点的右子树设置成当前节点的右子树的左子树 200 newNode.right=right.left; 201 //把当前节点的值替换成右子树的值 202 newNode.value=right.value; 203 //把当前节点的右子树设置成当前节点的右子树的右子树 204 right=right.right; 205 //把当前节点的左子树设置成新的节点 206 left=newNode; 207 208 // 查找要删除的节点 209 /** 210 * 211 * @param value 希望删除的节点的值 212 * @return 找到返回,没有返回null 213 */ 214 public Node search(int value) 215 if (value == this.value) 216 return this; 217 else if (value < this.value) // 如果查找的值小于当前节点,向左子树递归查找 218 if (this.left == null) 219 return null; 220 221 return this.left.search(value); 222 else // 如果查找的值不小于当前节点,向右子树递归查找 223 if (this.right == null) 224 return null; 225 226 return this.right.search(value); 227 228 229 230 // 查找要删除节点的父节点 231 /** 232 * 233 * @param value 要找到的节点的值 234 * @return 找到返回的是要删除节点的父节点的值,否则返回null 235 */ 236 public Node searchParent(int value) 237 // 如果当前节点是要删除节点的父节点,就返回 238 if ((this.left != null && this.left.value == value) || (this.right != null && this.right.value == value)) 239 return this; 240 else 241 // 如果查找的值小于当前节点的值,并且当前节点的左子节点不为空 242 if (value < this.value && this.left != null) 243 return this.left.searchParent(value);// 向左子树递归查找 244 else if (value >= this.value && this.right != null) 245 return this.right.searchParent(value);// 向右子树递归查找 246 else 247 return null;// 没有找到父节点 248 249 250 251 252 // 添加节点的方法 253 // 递归的形式添加节点,注意需要满足二叉排序树的要求 254 public void add(Node node) 255 if (node == null) 256 return; 257 258 // 判断传入的节点的值,和当前子树的根节点的值关系 259 if (node.value < this.value) 260 // 如果当前节点的左子节点为null 261 if (this.left == null) 262 this.left = node; 263 else // 递归向左子树添加 264 this.left.add(node); 265 266 else 267 // 如果当前节点的右子节点为null 268 if (this.right == null) 269 this.right = node; 270 else // 递归向右子树添加 271 this.right.add(node); 272 273 274 //当添加完一个节点后,如果:右子树的高度-左子树的高度>1,左旋转 275 if(rightHeight()-leftHeight()>1) 276 //如果它的右子树的左子树的高度大于它的右子树的高度 277 if(right!=null&&right.leftHeight()>right.rightHeight()) 278 //先对右子节点进行右旋转 279 right.rightRotate(); 280 //再对当前节点进行左旋转 281 leftRotate(); 282 else 283 leftRotate(); 284 285 return;//必须要 286 287 //当添加完一个节点后,如果:左子树的高度-右子树的高度>1,右旋转 288 if(leftHeight()-rightHeight()>1) 289 //如果它的左子树的右子树的高度大于它的左子树的高度 290 if(left!=null && left.rightHeight()>left.leftHeight()) 291 //先对当前节点的左节点进行左旋转 292 left.leftRotate(); 293 //再对当前节点进行右旋转 294 rightRotate(); 295 else 296 rightRotate(); 297 298 299 300 301 // 中序遍历二叉树 302 public void infixOrder() 303 if (this.left != null) 304 this.left.infixOrder(); 305 306 System.out.println(this); 307 if (this.right != null) 308 this.right.infixOrder(); 309 310 311
以上是关于D13-平衡二叉树[Java数据结构和算法]的主要内容,如果未能解决你的问题,请参考以下文章