平衡二叉树-Java
2016-04-27 23:32
429 查看
AVL是最先发明的自平衡二叉查找树算法。在AVL中任何节点的两个儿子子树的高度最大差别为一,所以它也被称为高度平衡树,n个结点的AVL树最大深度约1.44log2n。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。
package com.gloomy.Tree; import java.util.ArrayDeque; import java.util.Queue; import java.util.Stack; /** * 平衡二叉树 * * @author 过路的守望 * */ public class AVLTree { /* * 平衡二叉树的更 */ private Node root; public AVLTree(Node root) { this.root = root; } public static void main(String[] args) { Node A = new Node(1); Node B = new Node(2); Node C = new Node(3); Node D = new Node(4); Node E = new Node(5); Node F = new Node(6); Node G = new Node(7); Node H = new Node(8); Node I = new Node(9); Node J = new Node(10); Node K = new Node(11); Node L = new Node(12); Node M = new Node(13); Node N = new Node(14); AVLTree avlTree = new AVLTree(C); avlTree.insert(D); avlTree.insert(E); avlTree.insert(A); avlTree.insert(B); avlTree.insert(F); avlTree.insert(G); avlTree.insert(M); avlTree.insert(N); avlTree.insert(J); avlTree.insert(H); avlTree.insert(I); avlTree.insert(K); avlTree.insert(L); avlTree.remove(G); avlTree.remove(M); avlTree.remove(E); avlTree.remove(F); avlTree.remove(D); avlTree.remove(I); avlTree.remove(J); System.out.println(avlTree.findMax().val); System.out.println(avlTree.findMin().val); avlTree.levelOrder(avlTree.root); avlTree.preOrder(avlTree.root); avlTree.inOrder(avlTree.root); avlTree.postOrder(avlTree.root); } /** * 平衡二叉树中是否包含节点node * * @param node * @return */ public boolean contains(Node node) { /* * 平衡二叉树为空,自然不包含 */ if (root == null) { return false; } Node currentNode = root; /* * 标记node是否大于当前节点 */ int flag = node.compareTo(currentNode); /* * 检查平衡二叉树中是否包含节点node */ while (flag != 0) { if (flag > 0) { currentNode = currentNode.right; } else { currentNode = currentNode.left; } /* * 平衡二叉树树中为找到节点node,放回false。 */ if (currentNode == null) { return false; } flag = node.compareTo(currentNode); } return true; } /** * 递归检查平衡二叉树中root是否包含node节点 * * @param node * @param root */ public boolean contains(Node node, Node root) { /* * root为空显然不包含节点node */ if (root == null) { return false; } int flag = node.compareTo(root); /* * 在root的右子树中检查是否含有node节点 */ if (flag > 0) { return contains(node, root.right); } /* * 在root的左子树中检查是否含有node节点 */ if (flag < 0) { return contains(node, root.left); } /* * root中含有此节点,返回true */ return true; } /** * 返回平衡二叉树中的最大节点 * * @return */ public Node findMax() { return findMax(root); } /** * 返回平衡二叉树中的最小节点 * * @return */ public Node findMin() { return findMin(root); } /** * 找到平衡二叉树root中的最大节点 * * @param root * @return */ private Node findMax(Node root) { /** * root节点为空 */ if (root == null) { return null; } /* * 找到右子树中的最大元素节点 */ Node currentNode = root; while (currentNode.right != null) { currentNode = currentNode.right; } return currentNode; } /** * 递归查找平衡二叉树中的最大节点 * * @param root * @return */ private Node findMaxRec(Node root) { if (root == null) { return null; } if (root.right != null) { return findMaxRec(root.right); } return root; } /** * 查找平衡二叉树root中的最小节点 * * @param node * @param root * @return */ private Node findMin(Node root) { /* * root为空 */ if (root == null) { } /* * 在左子树中寻找最小节点元素 */ Node currentNode = root; while (currentNode.left != null) { currentNode = currentNode.left; } return currentNode; } /** * 递归查找平衡二叉树中的最小元素 * * @param root * @return */ private Node findMinRec(Node root) { /* * root 为空 */ if (root == null) { return root; } if (root.left != null) { return findMinRec(root.left); } return root; } /** * 返回节点node的高度,node如果为null,则高度为-1 * * @param node * @return */ private int getHeight(Node node) { return node == null ? -1 : node.hight; } /** * 单旋转-右旋 * * @param node * @return */ private Node rolateWithLeftChild(Node node) { Node leftChild = node.left; node.left = leftChild.right; leftChild.right = node; /* * 更新节点高度 */ node.hight = 1 + Math.max(getHeight(node.left), getHeight(node.right)); leftChild.hight = 1 + Math.max(getHeight(leftChild.left), getHeight(leftChild.right)); return leftChild; } /** * 单旋转-左旋 * * @param node * @return */ private Node rolateWithRightChild(Node node) { Node rightChild = node.right; node.right = rightChild.left; rightChild.left = node; /* * 更新节点高度 */ node.hight = 1 + Math.max(getHeight(node.left), getHeight(node.right)); rightChild.hight = 1 + Math.max(getHeight(rightChild.left), getHeight(rightChild.right)); return rightChild; } /** * 双旋转-RL * * @param node * @return */ private Node doubleWithLeftChild(Node node) { node.left = rolateWithRightChild(node.left); return rolateWithLeftChild(node); } /** * 双旋转-LR * * @param node * @return */ private Node doubleWithRightChild(Node node) { node.right = rolateWithLeftChild(node.right); return rolateWithRightChild(node); } /** * 向平衡二叉树中插入节点node * * @param node */ public void insert(Node node) { /* * 更新引用(传值) */ root = insert(node, root); } /** * 删除平衡二叉树中的节点node * * @param node */ public void remove(Node node) { root = remove(node, root); } /** * 递归实现向root平衡二叉树中插入元素node * * @param node * @param root * @return */ private Node insert(Node node, Node root) { if (root == null) { root = new Node(node.val); } int flag = node.compareTo(root); if (flag > 0) { root.right = insert(node, root.right); /* * 左右子树高度差 */ flag = Math.abs(getHeight(root.left) - getHeight(root.right)); if (flag == 2) { /* * RR型 */ if (getHeight(root.right.right) > getHeight(root.right.left)) { root = rolateWithRightChild(root); } /* * RL型 */ else { root = doubleWithRightChild(root); } } } else if (flag < 0) { root.left = insert(node, root.left); /* * 左右子树高度差 */ flag = Math.abs(getHeight(root.left) - getHeight(root.right)); if (flag == 2) { /* * LL型 */ if (getHeight(root.left.left) > getHeight(root.left.right)) { root = rolateWithLeftChild(root); } /* * LR型 */ else { root = doubleWithLeftChild(root); } } } /* * 更新root的高度 上层的高度由子树的高度决定 */ root.hight = 1 + Math.max(getHeight(root.left), getHeight(root.right)); return root; } /** * 递归删除二叉平衡树root中的节点node * * @param node * @param root * @return */ private Node remove(Node node, Node root) { /* * root为空 */ if (root == null) { return null; } int flag = node.compareTo(root); /* * 待删除节点在右子树上 */ if (flag > 0) { root.right = remove(node, root.right); } /* * 待删除节点在左子树上 */ if (flag < 0) { root.left = remove(node, root.left); } /* * 找到待删除节点 */ if (flag == 0) { if (root.left != null && root.right != null) { /* * 用待删除节点右子树上的最小节点的与待删除节点交换,然后问题变为删除节点replaceNode */ Node replaceNode = findMin(root.right); root.val = replaceNode.val; root.right = remove(replaceNode, root.right); } else { root = root.right == null ? root.left : root.right; } } if (root != null) { flag = Math.abs(getHeight(root.left) - getHeight(root.right)); } else { flag = 0; } if (flag == 2) { if (getHeight(root.left) > getHeight(root.right)) { /* * LL型旋转 */ if (getHeight(root.left.left) > getHeight(root.left.right)) { root = rolateWithLeftChild(root); } /* * LR型旋转 */ else { root = doubleWithLeftChild(root); } } else { /* * RR型旋转 */ if (getHeight(root.right.right) > getHeight(root.right.left)) { root = rolateWithRightChild(root); } /* * RL型旋转 */ else { root = doubleWithRightChild(root); } } } /* * 更新root的高度 */ if (root != null) { root.hight = 1 + Math.max(getHeight(root.left), getHeight(root.right)); } return root; } /** * 非递归先序遍历 * * @param node */ public void preOrder(Node node) { if (node == null) { return; } System.out.println("先序遍历:"); Stack<Node> stack = new Stack<Node>(); stack.push(node); while (!stack.isEmpty()) { node = stack.pop(); System.out.print(node.val + " "); /* * 先加入右儿子 */ if (node.right != null) { stack.push(node.right); } if (node.left != null) { stack.push(node.left); } } System.out.println(); } /** * 非递归中序遍历 * * @param node */ public void inOrder(Node node) { if (node == null) { return; } System.out.println("中序遍历:"); Stack<Node> stack = new Stack<Node>(); while (node != null || !stack.isEmpty()) { while (node != null) { stack.push(node); node = node.left; } /* * 处理完左子树,根节点,处理右子树。 */ node = stack.pop(); System.out.print(node.val + " "); node = node.right; } System.out.println(); } /** * 非递归后序遍历 * * @param node */ public void postOrder(Node node) { if (node == null) { return; } System.out.println("后序遍历:"); Stack<Node> stack = new Stack<Node>(); /* * preNode记录前一个出栈的节点 */ Node preNode = null; while (node != null || !stack.isEmpty()) { while (node != null) { stack.push(node); node = node.left; } node = stack.peek(); /* * 处理完左子树,在处理右子树,最后处理根节点。 */ while (node.right == null || node.right == preNode) { System.out.print(node.val + " "); stack.pop(); preNode = node; if (stack.isEmpty()) { System.out.println(); return; } node = stack.peek(); } node = node.right; } } public void levelOrder(Node node) { if (node == null) { return; } System.out.println("层序遍历:"); Queue<Node> queue = new ArrayDeque<Node>(); queue.offer(node); /* * 处理完上一层厚再处理下一层 */ while (!queue.isEmpty()) { node = queue.poll(); System.out.print(node.val + " "); if (node.left != null) { queue.offer(node.left); } if (node.right != null) { queue.offer(node.right); } } System.out.println(); } } /** * 平衡二叉树节点类 * * @author 过路的守望 */ class Node implements Comparable<Node> { /* * val 节点值 height 节点高度 */ int val; Node left; Node right; int hight; public Node(int val) { this.val = val; } @Override public int compareTo(Node o) { return this.val - o.val; } }
相关文章推荐
- DropWizard:用Java轻轻的写一个RESTful Service
- java--集合
- Java语言中没有引用传递,只有值传递。到底对不对?
- java文件读写操作大全
- Spring之单例类创建实例
- spring框架学习笔记(九)
- Java类加载器深入理解
- Java ArrayList 的不同排序方法
- java.util.regex.PatternSyntaxException: Unclosed character class near index解决办法
- java 基础一
- SpringMVC注解@initbinder解决类型转换问题
- RxJava Single&Subjects
- java编写简易扑克牌游戏
- 抽象类和接口
- 关于read与readLine方法的差别,留给初学java的童鞋的,周六会更新详细解析
- Java ,从char 和 Character到内存分配
- 2016.4.27
- Struts2 Annotation 注解配置
- Java中堆内存和栈内存详解
- Java中的泛型