平衡二叉树

平衡二叉树特点:对于任意一个节点,左子树和右子树的高度差不能超过1

下图就是一棵平衡二叉树:

image.png

  • 标注节点的高度:(叶子节点的高度为1)

image.png

  • 计算平衡因子:(这里是根据左子树高度减去右子树高度进行计算):

image.png

计算节点的高度和平衡因子

  1. public class AVLTree<K extends Comparable<K>,V>{
  2. private class Node{
  3. public K key;
  4. public V value;
  5. public Node left,right;
  6. public int height;
  7. public Node(K key,V value){
  8. this.key=key;
  9. this.value=value;
  10. this.left=null;
  11. this.right=null;
  12. //叶子节点的高度是1
  13. height=1;
  14. }
  15. }
  16. private Node root;
  17. private int size;
  18. public void add(K key, V value) {
  19. root=add(root,key,value);
  20. }
  21. //计算节点的高度
  22. private int getNodeHeight(Node node){
  23. if(node==null){
  24. return 0;
  25. }
  26. return node.height;
  27. }
  28. //获取节点的平衡因子,左子树高度-右子树高度
  29. private int getBalancedFactor(Node node){
  30. if(node==null){
  31. return 0;
  32. }
  33. return getNodeHeight(node.left)-getNodeHeight(node.right);
  34. }
  35. private Node add(Node node,K key,V value){
  36. if(node==null){
  37. size++;
  38. return new Node(key,value);
  39. }
  40. if(key.compareTo(node.key)<0){
  41. node.left=add(node.left,key,value);
  42. }else if(key.compareTo(node.key)>0){
  43. node.right=add(node.right,key,value);
  44. }else{
  45. node.value=value;
  46. }
  47. //更新height
  48. node.height=1+Math.max(getNodeHeight(node.left),getNodeHeight(node.right));
  49. //计算平衡因子
  50. int balancedFactor=getBalancedFactor(node);
  51. if(Math.abs(balancedFactor)>1){
  52. System.out.println("unblance:"+balancedFactor);
  53. }
  54. return node;
  55. }
  56. }

检查二分搜索树和平衡树

  • 利用BST中序遍历性质,判断是否是BST
  1. //检查该树是否是平衡二叉树
  2. public boolean isBST(){
  3. List<K> keys=new ArrayList<>();
  4. inOrder(root,keys);
  5. for(int i=1;i<keys.size();i++){
  6. if(keys.get(i-1).compareTo(keys.get(i))>0){
  7. return false;
  8. }
  9. }
  10. return true;
  11. }
  12. private void inOrder(Node node, List<K> keys){
  13. if(node==null){
  14. return;
  15. }
  16. inOrder(node.left,keys);
  17. keys.add(node.key);
  18. inOrder(node.right,keys);
  19. }
  • 判断该树是否是平衡树
  1. //判断该二叉树是否是一棵平衡二叉树
  2. public boolean isBalancedTree(){
  3. return isBalancedTree(root);
  4. }
  5. private boolean isBalancedTree(Node node){
  6. if(node==null){
  7. return true;
  8. }
  9. int balancedFactor=getBalancedFactor(node);
  10. if(Math.abs(balancedFactor)>1){
  11. return false;
  12. }
  13. return isBalancedTree(node.left) && isBalancedTree(node.right);
  14. }

AVL树的左旋转和右旋转

  • AVL树的右旋转:插入的元素在不平衡的节点的左侧的左侧

image.png

  • 右旋转针对的情况:以x、z为根节点的子树是平衡的BST树,添加一个元素以y为根节点的子树就不是平衡二叉树了

image.png

  • 右旋转操作I:x.right=y

image.png

  • 右旋转操作II:y.left=T3

image.png

  • 右旋转之后,就是平衡的BST:假设z节点的高度是(h+1),可以验证以x为根节点的BST树是平衡树

image.png

  • 代码实现:
  1. // 对节点y进行向右旋转操作,返回旋转后新的根节点x
  2. // y x
  3. // / \ / \
  4. // x T4 向右旋转 (y) z y
  5. // / \ - - - - - - - -> / \ / \
  6. // z T3 T1 T2 T3 T4
  7. // / \
  8. // T1 T2
  9. private Node rightRotate(Node y){
  10. Node x=y.left;
  11. Node T3=x.right;
  12. //向右旋转
  13. x.right=y;
  14. y.left=T3;
  15. //维护树的高度
  16. y.height=1 + Math.max(getNodeHeight(y.left),getNodeHeight(y.right));
  17. x.height=1 + Math.max(getNodeHeight(x.left),getNodeHeight(x.right));
  18. return x;
  19. }
  20. private Node add(Node node,K key,V value){
  21. if(node==null){
  22. size++;
  23. return new Node(key,value);
  24. }
  25. if(key.compareTo(node.key)<0){
  26. node.left=add(node.left,key,value);
  27. }else if(key.compareTo(node.key)>0){
  28. node.right=add(node.right,key,value);
  29. }else{
  30. node.value=value;
  31. }
  32. //更新height
  33. node.height=1+Math.max(getNodeHeight(node.left),getNodeHeight(node.right));
  34. //计算平衡因子
  35. int balancedFactor=getBalancedFactor(node);
  36. if(Math.abs(balancedFactor)>1){
  37. System.out.println("unblance:"+balancedFactor);
  38. }
  39. //平衡维护-->右旋转
  40. if(balancedFactor>1 && getBalancedFactor(node.left)>=0){
  41. return rightRotate(node);
  42. }
  43. return node;
  44. }
  • AVL的左旋转
  1. // 对节点y进行向左旋转操作,返回旋转后新的根节点x
  2. // y x
  3. // / \ / \
  4. // T1 x 向左旋转 (y) y z
  5. // / \ - - - - - - - -> / \ / \
  6. // T2 z T1 T2 T3 T4
  7. // / \
  8. // T3 T4
  9. private Node leftRotate(Node y){
  10. Node x=y.right;
  11. Node T2=x.left;
  12. //向左旋转
  13. x.left=y;
  14. y.right=T2;
  15. //维护高度
  16. y.height=1+Math.max(getNodeHeight(y.left),getNodeHeight(y.right));
  17. x.height=1+Math.max(getNodeHeight(x.left),getNodeHeight(x.right));
  18. return x;
  19. }
  20. private Node add(Node node,K key,V value){
  21. if(node==null){
  22. size++;
  23. return new Node(key,value);
  24. }
  25. if(key.compareTo(node.key)<0){
  26. node.left=add(node.left,key,value);
  27. }else if(key.compareTo(node.key)>0){
  28. node.right=add(node.right,key,value);
  29. }else{
  30. node.value=value;
  31. }
  32. //更新height
  33. node.height=1+Math.max(getNodeHeight(node.left),getNodeHeight(node.right));
  34. //计算平衡因子
  35. int balancedFactor=getBalancedFactor(node);
  36. if(Math.abs(balancedFactor)>1){
  37. System.out.println("unblance:"+balancedFactor);
  38. }
  39. //平衡维护-->右旋转
  40. if(balancedFactor>1 && getBalancedFactor(node.left)>=0){
  41. return rightRotate(node);
  42. }
  43. if(balancedFactor<-1 && getBalancedFactor(node.right)<=0){
  44. return leftRotate(node);
  45. }
  46. return node;
  47. }

LR和RL

  • LR

image.pngimage.png

  • RLimage.pngimage.png
  1. //计算平衡因子
  2. int balancedFactor=getBalancedFactor(node);
  3. /*if(Math.abs(balancedFactor)>1){
  4. System.out.println("unblance:"+balancedFactor);
  5. }*/
  6. //平衡维护
  7. //LL
  8. if(balancedFactor>1 && getBalancedFactor(node.left)>=0){
  9. return rightRotate(node);
  10. }
  11. //RR
  12. if(balancedFactor<-1 && getBalancedFactor(node.right)<=0){
  13. return leftRotate(node);
  14. }
  15. //LR
  16. if(balancedFactor>1 && getBalancedFactor(node.left)<0){
  17. Node x=node.left;
  18. node.left=leftRotate(x);
  19. //LL
  20. return rightRotate(node);
  21. }
  22. //RL
  23. if(balancedFactor<-1 && getBalancedFactor(node.right)>0){
  24. Node x=node.right;
  25. node.right=rightRotate(x);
  26. //RR
  27. return leftRotate(node);
  28. }

删除元素

  1. //从AVL中删除值为key的元素
  2. public V remove(K key) {
  3. Node node=getNode(root,key);
  4. if(node!=null){
  5. root=del(root,key);
  6. size--;
  7. }
  8. return null;
  9. }
  10. //获取Map中的最小的key
  11. private Node min(Node node){
  12. if(node.left==null){
  13. return node;
  14. }
  15. return min(node.left);
  16. }
  17. //删除以node为根结点的Map中的key最小的元素
  18. private Node delMin(Node node){
  19. if(node.left==null){
  20. Node nodeRight=node.right;
  21. node.right=null;
  22. size--;
  23. return nodeRight;
  24. }
  25. node.left=delMin(node.left);
  26. //更新height
  27. node.height=1+Math.max(getNodeHeight(node.left),getNodeHeight(node.right));
  28. //维护平衡
  29. return keepBalance(node);
  30. }
  31. ////删除以node为根结点的Map中的键值为key的元素
  32. private Node del(Node node, K key){
  33. if(node==null){
  34. return null;
  35. }
  36. //记录删除元素后,该BST的新的根节点
  37. Node retNode=null;
  38. if(key.compareTo(node.key)<0){
  39. node.left=del(node.left,key);
  40. retNode=node;
  41. }else if(key.compareTo(node.key)>0){
  42. node.right=del(node.right,key);
  43. retNode=node;
  44. }else{
  45. //节点node就是要删除的节点
  46. //该节点只右有子树
  47. if(node.left==null){
  48. Node rightNode=node.right;
  49. node.right=null;
  50. size--;
  51. retNode=rightNode;
  52. }else if(node.right==null){ //该节点只有左子树
  53. Node leftNode=node.left;
  54. node.left=null;
  55. size--;
  56. retNode=leftNode;
  57. }else{
  58. //删除既有左子树又有右子树的节点
  59. Node s=min(node.right);
  60. s.right=delMin(node.right);
  61. s.left=node.left;
  62. //删除node
  63. node.left=node.right=null;
  64. retNode=s;
  65. }
  66. }
  67. if(retNode==null){
  68. return retNode;
  69. }
  70. //更新height
  71. retNode.height=1+Math.max(getNodeHeight(retNode.left),getNodeHeight(retNode.right));
  72. //保持平衡
  73. return keepBalance(retNode);
  74. }
  75. //维护以node为根节点的二叉树是平衡二叉树
  76. private Node keepBalance(Node node){
  77. //计算平衡因子
  78. int balancedFactor=getBalancedFactor(node);
  79. //平衡维护
  80. //LL
  81. if(balancedFactor>1 && getBalancedFactor(node.left)>=0){
  82. return rightRotate(node);
  83. }
  84. //RR
  85. if(balancedFactor<-1 && getBalancedFactor(node.right)<=0){
  86. return leftRotate(node);
  87. }
  88. //LR
  89. if(balancedFactor>1 && getBalancedFactor(node.left)<0){
  90. Node x=node.left;
  91. node.left=leftRotate(x);
  92. //LL
  93. return rightRotate(node);
  94. }
  95. //RL
  96. if(balancedFactor<-1 && getBalancedFactor(node.right)>0){
  97. Node x=node.right;
  98. node.right=rightRotate(x);
  99. //RR
  100. return leftRotate(node);
  101. }
  102. return node;
  103. }

基于AVL树的集合和映射

  • AVL Map
  1. public class AVLMap<K extends Comparable<K>,V> implements Map<K,V> {
  2. private AVLTree<K,V> avlTree;
  3. public AVLMap(){
  4. avlTree=new AVLTree<>();
  5. }
  6. @Override
  7. public void add(K key, V value) {
  8. avlTree.add(key,value);
  9. }
  10. @Override
  11. public V remove(K key) {
  12. return avlTree.remove(key);
  13. }
  14. @Override
  15. public boolean contains(K key) {
  16. return avlTree.contains(key);
  17. }
  18. @Override
  19. public V get(K key) {
  20. return avlTree.get(key);
  21. }
  22. @Override
  23. public void set(K key, V newValue) {
  24. avlTree.set(key,newValue);
  25. }
  26. @Override
  27. public int getSize() {
  28. return avlTree.getSize();
  29. }
  30. @Override
  31. public boolean isEmpty() {
  32. return avlTree.isEmpty();
  33. }
  34. }
  • AVL Set