当前位置:   article > 正文

数据结构(13):平衡二叉树(AVL)实现_平衡二叉树高度与结点

平衡二叉树高度与结点

一、平衡二叉树定义

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

特性:平衡二叉树的高度和节点数量之间的关系是O(logn)。

二、标注

1.平衡因子:左右两个子树的高度差。如果平衡因子绝对值>=2,则不是平衡二叉树,如下图

三、平衡基本操作

1.右旋转

(1)原始树
 
(2)右旋转:旋转为
 
(3)证明右旋转后,满足平衡二叉树和二分搜索树(节点,大于左孩子,小于右孩子)的性质。

2.左旋转

(1)原始树
 
(2)左旋转

3.LR


(1)原始树
 
(2)先将x左旋转,转换为LL
 
(3)再进行右旋转


4.RL

(1)原始树
 
(2)先堆X节点进行右旋转,为RR
 
(3)再对y进行左旋转

四、AVL实现代码

  1. package com.DataStructures._12AVL;
  2. import java.util.ArrayList;
  3. /**
  4.  * Created by Administrator on 2019/11/23.
  5.  */
  6. public class AVLTree <K extends Comparable<K>, V> {
  7.     private class Node{
  8.         public K key;
  9.         public V value;
  10.         public Node left, right;
  11.         public int height; //每个节点的高度值
  12.         public Node(K key, V value){
  13.             this.key = key;
  14.             this.value = value;
  15.             left = null;
  16.             right = null;
  17.             height=1;
  18.         }
  19.     }
  20.     private Node root;
  21.     private int size;
  22.     public AVLTree(){
  23.         root = null;
  24.         size = 0;
  25.     }
  26.     public int getSize(){
  27.         return size;
  28.     }
  29.     public boolean isEmpty(){
  30.         return size == 0;
  31.     }
  32.     //=======================辅助函数 start=================================
  33.     //返回当前节点node的高度
  34.     private int getHeight(Node node){
  35.         if (node==null){
  36.             return 0;
  37.         }
  38.         return node.height;
  39.     }
  40.     //计算每个节点的平衡因子
  41.     //平衡因子>=2或则<=-2时,则有问题
  42.     private int getBalanceFactor(Node node){
  43.         if(node==null){
  44.             return 0;
  45.         }
  46.         return  getHeight(node.left)-getHeight(node.right);
  47.     }
  48.     //判断当前树是否时二分搜索树:通过中序遍历,由小到打
  49.     //二分搜索树:所有节点满足,左子节点小于根节点,右子节点大于根节点
  50.     public boolean isBST(){
  51.         ArrayList<K> keys=new ArrayList<K>();
  52.         inOrder(root,keys);
  53.         for (int i = 1; i < keys.size(); i++) {
  54.             if(keys.get(i-1).compareTo(keys.get(i))>0){
  55.                 return false;
  56.             }
  57.         }
  58.         return true;
  59.     }
  60.     private void inOrder(Node node,ArrayList<K> keys){
  61.         if (node==null){
  62.             return;
  63.         }
  64.         inOrder(node.left,keys);
  65.         keys.add(node.key);
  66.         inOrder(node.right,keys );
  67.     }
  68.     //判断该二叉树,是否是一个平衡二叉树
  69.     public boolean isBalanced(){
  70.         return isBalanced(root);
  71.     }
  72.     //判断以Node为根的二叉树是否是一个平衡二叉树,使用递归算法
  73.     public boolean isBalanced(Node node){
  74.         if(node==null)
  75.             return true;
  76.         int balanceFactor=getBalanceFactor(node);
  77.         if(Math.abs(balanceFactor)>1){
  78.             return false;
  79.         }
  80.         return isBalanced(node.left) && isBalanced(node.right);
  81.     }
  82.     //=======================辅助函数 end=================================
  83.     // 向二分搜索树中添加新的元素(key, value)
  84.     public void add(K key, V value){
  85.         root = add(root, key, value);
  86.     }
  87.     // 向以node为根的二分搜索树中插入元素(key, value),递归算法
  88.     // 返回插入新节点后二分搜索树的根
  89.     private Node add(Node node, K key, V value){
  90.         if(node == null){
  91.             size ++;
  92.             return new Node(key, value);
  93.         }
  94.         if(key.compareTo(node.key) < 0)
  95.             node.left = add(node.left, key, value);
  96.         else if(key.compareTo(node.key) > 0)
  97.             node.right = add(node.right, key, value);
  98.         else // key.compareTo(node.key) == 0
  99.             node.value = value;
  100.         //1.更新height
  101.         node.height=1+Math.max(getHeight(node.left),getHeight(node.right));
  102.         //2.计算平衡因子
  103.         int balanceFactor=getBalanceFactor(node);
  104. //        if(Math.abs(balanceFactor)>1){
  105. //            System.out.println("unbalanced : "+balanceFactor);
  106. //        }
  107.         //3.如果平衡因子大于1,则维护平衡性
  108.         //情况1【LL】:左侧大于右侧,而且左子树的平衡因子大于等于0,进行右旋转
  109.         if(balanceFactor>1&&getBalanceFactor(node.left)>=0){
  110.             return rightRotate(node);
  111.         }
  112.         //情况2【RR】:右侧大于左侧,而且右子树平衡因子小于等于0,即向右倾斜,进行左旋转
  113.         if (balanceFactor<-1&&getBalanceFactor(node.right)<=0){
  114.             return leftRotate(node);
  115.         }
  116.         //情况3【LR】
  117.         if(balanceFactor>1&&getBalanceFactor(node.left)<0){
  118.             node.left=leftRotate(node.left);
  119.             return rightRotate(node);
  120.         }
  121.         //情况4【RL】
  122.         if (balanceFactor<-1&&getBalanceFactor(node.right)>0){
  123.             node.right=rightRotate(node.right);
  124.             return leftRotate(node);
  125.         }
  126.         return node;
  127.     }
  128.     //右旋转
  129.     // 对节点y进行向右旋转操作,返回旋转后新的根节点x
  130.     //        y                              x
  131.     //       / \                           /   \
  132.     //      x   T4     向右旋转 (y)        z     y
  133.     //     / \       - - - - - - - ->    / \   / \
  134.     //    z   T3                       T1  T2 T3 T4
  135.     //   / \
  136.     // T1   T2
  137.     private Node rightRotate(Node y){
  138.         Node x=y.left;
  139.         Node T3=x.right;
  140.         //向右旋转
  141.         x.right=y;
  142.         y.left=T3;
  143.         //更新x,y的height值
  144.         y.height=Math.max(getHeight(y.left),getHeight(y.right))+1;
  145.         x.height=Math.max(getHeight(x.left),getHeight(x.right))+1;
  146.         return x;
  147.     }
  148.     //左旋转
  149.     // 对节点y进行向左旋转操作,返回旋转后新的根节点x
  150.     //    y                             x
  151.     //  /  \                          /   \
  152.     // T1   x      向左旋转 (y)       y     z
  153.     //     / \   - - - - - - - ->   / \   / \
  154.     //   T2  z                     T1 T2 T3 T4
  155.     //      / \
  156.     //     T3 T4
  157.     private Node leftRotate(Node y){
  158.         Node x=y.right;
  159.         Node T2=x.left;
  160.         //向左旋转
  161.         x.left=y;
  162.         y.right=T2;
  163.         //更新height
  164.         y.height=Math.max(getHeight(y.left),getHeight(y.right))+1;
  165.         x.height=Math.max(getHeight(x.left),getHeight(x.right))+1;
  166.         return x;
  167.     }
  168.     // 返回以node为根节点的二分搜索树中,key所在的节点
  169.     private Node getNode(Node node, K key){
  170.         if(node == null)
  171.             return null;
  172.         if(key.equals(node.key))
  173.             return node;
  174.         else if(key.compareTo(node.key) < 0)
  175.             return getNode(node.left, key);
  176.         else // if(key.compareTo(node.key) > 0)
  177.             return getNode(node.right, key);
  178.     }
  179.     public boolean contains(K key){
  180.         return getNode(root, key) != null;
  181.     }
  182.     public V get(K key){
  183.         Node node = getNode(root, key);
  184.         return node == null ? null : node.value;
  185.     }
  186.     public void set(K key, V newValue){
  187.         Node node = getNode(root, key);
  188.         if(node == null)
  189.             throw new IllegalArgumentException(key + " doesn't exist!");
  190.         node.value = newValue;
  191.     }
  192.     // 返回以node为根的二分搜索树的最小值所在的节点
  193.     private Node minimum(Node node){
  194.         if(node.left == null)
  195.             return node;
  196.         return minimum(node.left);
  197.     }
  198.     // 删除掉以node为根的二分搜索树中的最小节点
  199.     // 返回删除节点后新的二分搜索树的根
  200.     private Node removeMin(Node node){
  201.         if(node.left == null){
  202.             Node rightNode = node.right;
  203.             node.right = null;
  204.             size --;
  205.             return rightNode;
  206.         }
  207.         node.left = removeMin(node.left);
  208.         return node;
  209.     }
  210.     // 从二分搜索树中删除键为key的节点
  211.     public V remove(K key){
  212.         Node node = getNode(root, key);
  213.         if(node != null){
  214.             root = remove(root, key);
  215.             return node.value;
  216.         }
  217.         return null;
  218.     }
  219.     private Node remove(Node node, K key){
  220.         if( node == null )
  221.             return null;
  222.         //最终要返回的node
  223.         Node retNode;
  224.         if( key.compareTo(node.key) < 0 ){
  225.             node.left = remove(node.left , key);
  226. //            return node;
  227.             retNode=node;
  228.         }
  229.         else if(key.compareTo(node.key) > 0 ){
  230.             node.right = remove(node.right, key);
  231. //            return node;
  232.             retNode=node;
  233.         }
  234.         else{   // key.compareTo(node.key) == 0
  235.             if(node.left == null){   // 待删除节点左子树为空的情况
  236.                 Node rightNode = node.right;
  237.                 node.right = null;
  238.                 size --;
  239. //                return rightNode;
  240.                 retNode=rightNode;
  241.             }else  if(node.right == null){  // 待删除节点右子树为空的情况
  242.                 Node leftNode = node.left;
  243.                 node.left = null;
  244.                 size --;
  245. //                return leftNode;
  246.                 retNode=leftNode;
  247.             }else {     // 待删除节点左右子树均不为空的情况
  248.                 // 找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
  249.                 // 用这个节点顶替待删除节点的位置
  250.                 Node successor = minimum(node.right);
  251. //            successor.right = removeMin(node.right);  //可能会引起删除值
  252.                 successor.right=remove(node.right,successor.key);//服用remove的调整方法
  253.                 successor.left = node.left;
  254.                 node.left = node.right = null;
  255. //            return successor;
  256.                 retNode=successor;
  257.             }
  258.         }
  259. //        当retNode为空的时候,则直接返回
  260.         if (retNode==null){
  261.             return null;
  262.         }
  263.         //1.更新height
  264.         retNode.height=1+Math.max(getHeight(retNode.left),getHeight(retNode.right));
  265.         //2.计算平衡因子
  266.         int balanceFactor=getBalanceFactor(retNode);
  267. //        if(Math.abs(balanceFactor)>1){
  268. //            System.out.println("unbalanced : "+balanceFactor);
  269. //        }
  270.         //3.如果平衡因子大于1,则维护平衡性
  271.         //情况1【LL】:左侧大于右侧,而且左子树的平衡因子大于等于0,进行右旋转
  272.         if(balanceFactor>1&&getBalanceFactor(retNode.left)>=0){
  273.             return rightRotate(retNode);
  274.         }
  275.         //情况2【RR】:右侧大于左侧,而且右子树平衡因子小于等于0,即向右倾斜,进行左旋转
  276.         if (balanceFactor<-1&&getBalanceFactor(retNode.right)<=0){
  277.             return leftRotate(retNode);
  278.         }
  279.         //情况3【LR】
  280.         if(balanceFactor>1&&getBalanceFactor(retNode.left)<0){
  281.             retNode.left=leftRotate(retNode.left);
  282.             return rightRotate(retNode);
  283.         }
  284.         //情况4【RL】
  285.         if (balanceFactor<-1&&getBalanceFactor(retNode.right)>0){
  286.             node.right=rightRotate(retNode.right);
  287.             return leftRotate(retNode);
  288.         }
  289.         return retNode;
  290.     }
  291.     public static void main(String[] args){
  292.         System.out.println("Pride and Prejudice");
  293.         ArrayList<String> words = new ArrayList<>();
  294.         if(FileOperation.readFile("src/resources/pride-and-prejudice.txt", words)) {
  295.             System.out.println("Total words: " + words.size());
  296.             AVLTree<String, Integer> map = new AVLTree<>();
  297.             for (String word : words) {
  298.                 if (map.contains(word))
  299.                     map.set(word, map.get(word) + 1);
  300.                 else
  301.                     map.add(word, 1);
  302.             }
  303.             System.out.println("Total different words: " + map.getSize());
  304.             System.out.println("Frequency of PRIDE: " + map.get("pride"));
  305.             System.out.println("Frequency of PREJUDICE: " + map.get("prejudice"));
  306.             System.out.println("is BST : "+map.isBST());
  307.             System.out.println("is Balance : "+ map.isBalanced());
  308.             for (String word : words) {
  309.                 map.remove(word);
  310.                 if(!map.isBST()||!map.isBalanced()){
  311. //                    System.out.println("");
  312.                     throw new RuntimeException("Error: 非BST,或者非平衡树");
  313.                 }
  314.             }
  315.         }
  316.         System.out.println();
  317.     }
  318. }

五、基于AVL的集合和映射

1.集合

(1)接口

  1. package com.DataStructures._12AVL;
  2. /**
  3.  * Created by Administrator on 2018/12/17.
  4.  */
  5. public interface Set<E> {
  6.     void add(E e);
  7.     void remove(E e);
  8.     boolean contains(E e);
  9.     int getSize();
  10.     boolean isEmpty();
  11. }

(2)实现

  1. package com.DataStructures._12AVL;
  2. /**
  3.  * Created by Administrator on 2019/11/24.
  4.  */
  5. public class AVLSet <E extends Comparable<E>> implements Set<E> {
  6.     private AVLTree<E,Object> avl;
  7.     public AVLSet(){
  8.         avl=new AVLTree<E, Object>();
  9.     }
  10.     @Override
  11.     public void add(E e) {
  12.         avl.add(e,null);
  13.     }
  14.     @Override
  15.     public void remove(E e) {
  16.         avl.remove(e);
  17.     }
  18.     @Override
  19.     public boolean contains(E e) {
  20. //        return false;
  21.         return avl.contains(e);
  22.     }
  23.     @Override
  24.     public int getSize() {
  25. //        return 0;
  26.         return avl.getSize();
  27.     }
  28.     @Override
  29.     public boolean isEmpty() {
  30. //        return false;
  31.         return avl.isEmpty();
  32.     }
  33. }

2.映射map

(1)接口

  1. package com.DataStructures._12AVL;
  2. /**
  3.  * Created by Administrator on 2018/12/17.
  4.  */
  5. public interface Map<K,V> {
  6.     void add(K key, V value);
  7.     V remove(K key);
  8.     boolean contains(K key);
  9.     V get(K key);
  10.     void set(K key, V value);
  11.     int getSize();
  12.     boolean isEmpty();
  13. }

(2)实现

  1. package com.DataStructures._12AVL;
  2. /**
  3.  * Created by Administrator on 2019/11/24.
  4.  * AVLMap:基于AVL实现的Map
  5.  */
  6. public class AVLMap <K extends Comparable<K>,V> implements Map<K,V> {
  7.     private AVLTree<K,V> avl;
  8.     public AVLMap(){
  9.         avl=new AVLTree<>();
  10.     }
  11.     @Override
  12.     public int getSize(){
  13.         return avl.getSize();
  14.     }
  15.     @Override
  16.     public boolean isEmpty(){
  17.         return avl.isEmpty();
  18.     }
  19.     @Override
  20.     public void add(K key, V value){
  21.         avl.add(key, value);
  22.     }
  23.     @Override
  24.     public boolean contains(K key){
  25.         return avl.contains(key);
  26.     }
  27.     @Override
  28.     public V get(K key){
  29.         return avl.get(key);
  30.     }
  31.     @Override
  32.     public void set(K key, V newValue){
  33.         avl.set(key, newValue);
  34.     }
  35.     @Override
  36.     public V remove(K key){
  37.         return avl.remove(key);
  38.     }
  39. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/492130
推荐阅读
相关标签
  

闽ICP备14008679号